diff --git a/package-lock.json b/package-lock.json index cb7ecb3c..16eca2de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "1.6.2-rc.0", + "version": "1.6.2-rc.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f5b28d34..b8a27b5f 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "@splitsoftware/splitio-commons", - "version": "1.6.2-rc.0", + "version": "1.6.2-rc.4", "description": "Split Javascript SDK common components", "main": "cjs/index.js", "module": "esm/index.js", - "types": "types", + "types": "src/types.d.ts", "files": [ "README.md", "CONTRIBUTORS-GUIDE.md", @@ -12,15 +12,14 @@ "CHANGES.txt", "cjs", "esm", - "src", - "types" + "src" ], "scripts": { "check": "npm run check:lint && npm run check:types", "check:lint": "eslint src --ext .js,.ts", "check:types": "tsc --noEmit", "build": "npm run build:cjs && npm run build:esm", - "build:esm": "rimraf esm && tsc -m es2015 --outDir esm -d true --declarationDir types", + "build:esm": "rimraf esm types && tsc -m es2015 --outDir esm", "build:cjs": "rimraf cjs && tsc -m CommonJS --outDir cjs", "test": "jest", "test:coverage": "jest --coverage", diff --git a/src/__tests__/mocks/fetchSpecificSplits.ts b/src/__tests__/mocks/fetchSpecificSplits.ts index 8f9098c3..540c3d8f 100644 --- a/src/__tests__/mocks/fetchSpecificSplits.ts +++ b/src/__tests__/mocks/fetchSpecificSplits.ts @@ -1,4 +1,4 @@ -import { SplitIO } from '../../types'; +import { SplitFilter } from '../../types'; const valuesExamples = [ ['\u0223abc', 'abc\u0223asd', 'abc\u0223', 'abcȣ'], @@ -12,7 +12,7 @@ const valuesExamples = [ ['%', '%25', '__a', '__ш'], // [7] ordered and deduplicated ]; -export const splitFilters: SplitIO.SplitFilter[][] = [ +export const splitFilters: SplitFilter[][] = [ [ { type: 'byName', values: valuesExamples[0] }, { type: 'byName', values: valuesExamples[1] }, diff --git a/src/consent/__tests__/sdkUserConsent.spec.ts b/src/consent/__tests__/sdkUserConsent.spec.ts index e7981871..66740e38 100644 --- a/src/consent/__tests__/sdkUserConsent.spec.ts +++ b/src/consent/__tests__/sdkUserConsent.spec.ts @@ -33,10 +33,10 @@ test('createUserConsentAPI', () => { expect(storage.events.clear).toBeCalledTimes(1); // storage tracked data dropped expect(storage.impressions.clear).toBeCalledTimes(1); - // Invalid values have no effect - expect(props.setStatus('DECLINED')).toBe(false); // strings are not valid - expect(props.setStatus('GRANTED')).toBe(false); - expect(props.setStatus(undefined)).toBe(false); + // @ts-ignore Invalid values have no effect + expect(props.setStatus('DECLINED')).toBe(false); // @ts-ignore strings are not valid + expect(props.setStatus('GRANTED')).toBe(false); // @ts-ignore + expect(props.setStatus(undefined)).toBe(false); // @ts-ignore expect(props.setStatus({})).toBe(false); expect(syncManager.submitterManager.start).toBeCalledTimes(1); diff --git a/src/consent/sdkUserConsent.ts b/src/consent/sdkUserConsent.ts index e8f12156..40a7beda 100644 --- a/src/consent/sdkUserConsent.ts +++ b/src/consent/sdkUserConsent.ts @@ -3,9 +3,10 @@ import { isConsentGranted } from './index'; import { CONSENT_GRANTED, CONSENT_DECLINED, CONSENT_UNKNOWN } from '../utils/constants'; import { isBoolean } from '../utils/lang'; import { ISdkFactoryContext } from '../sdkFactory/types'; +import { IUserConsentAPI } from '../types'; // User consent enum -const ConsentStatus = { +const ConsentStatus: IUserConsentAPI['Status'] = { GRANTED: CONSENT_GRANTED, DECLINED: CONSENT_DECLINED, UNKNOWN: CONSENT_UNKNOWN, @@ -14,7 +15,7 @@ const ConsentStatus = { /** * The public user consent API exposed via SplitFactory, used to control if the SDK tracks and sends impressions and events or not. */ -export function createUserConsentAPI(params: ISdkFactoryContext) { +export function createUserConsentAPI(params: ISdkFactoryContext): IUserConsentAPI { const { settings, settings: { log }, syncManager, storage: { events, impressions, impressionCounts } } = params; if (!isConsentGranted(settings)) log.info(USER_CONSENT_INITIAL, [settings.userConsent]); @@ -51,7 +52,7 @@ export function createUserConsentAPI(params: ISdkFactoryContext) { }, getStatus() { - return settings.userConsent; + return settings.userConsent!; }, Status: ConsentStatus diff --git a/src/dtos/types.ts b/src/dtos/types.ts index a61e3777..0b5232af 100644 --- a/src/dtos/types.ts +++ b/src/dtos/types.ts @@ -1,5 +1,3 @@ -import { SplitIO } from '../types'; - export type MaybeThenable = T | Promise /** Split Matchers */ @@ -204,9 +202,3 @@ export interface IMetadata { /** host name */ n: string } - -export type ISplitFiltersValidation = { - queryString: string | null, - groupedFilters: Record, - validFilters: SplitIO.SplitFilter[] -}; diff --git a/src/evaluator/Engine.ts b/src/evaluator/Engine.ts index af65a87f..e4c307a4 100644 --- a/src/evaluator/Engine.ts +++ b/src/evaluator/Engine.ts @@ -5,10 +5,10 @@ import { thenable } from '../utils/promise/thenable'; import * as LabelsConstants from '../utils/labels'; import { CONTROL } from '../utils/constants'; import { ISplit, MaybeThenable } from '../dtos/types'; -import { SplitIO } from '../types'; +import { SplitKey, Attributes } from '../types'; import { IStorageAsync, IStorageSync } from '../storages/types'; import { IEvaluation, IEvaluationResult, IEvaluator, ISplitEvaluator } from './types'; -import { ILogger } from '../logger/types'; +import { ILogger } from '../types'; function evaluationResult(result: IEvaluation | undefined, defaultTreatment: string): IEvaluationResult { return { @@ -38,7 +38,7 @@ export class Engine { return this.baseInfo.name; } - getTreatment(key: SplitIO.SplitKey, attributes: SplitIO.Attributes | undefined, splitEvaluator: ISplitEvaluator): MaybeThenable { + getTreatment(key: SplitKey, attributes: Attributes | undefined, splitEvaluator: ISplitEvaluator): MaybeThenable { const { killed, seed, diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index b229a22b..94c0cfa4 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -1,5 +1,5 @@ import { findIndex } from '../../utils/lang'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { thenable } from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; import { IMatcher } from '../types'; diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index 2ecb95ff..770fa1b9 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -1,9 +1,9 @@ import { findIndex } from '../../utils/lang'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { thenable } from '../../utils/promise/thenable'; import * as LabelsConstants from '../../utils/labels'; import { CONTROL } from '../../utils/constants'; -import { SplitIO } from '../../types'; +import { SplitKey, Attributes } from '../../types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; import { ENGINE_COMBINER_IFELSEIF, ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, ERROR_ENGINE_COMBINER_IFELSEIF } from '../../logger/constants'; @@ -35,7 +35,7 @@ export function ifElseIfCombinerContext(log: ILogger, predicates: IEvaluator[]): return undefined; } - function ifElseIfCombiner(key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) { + function ifElseIfCombiner(key: SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: Attributes, splitEvaluator?: ISplitEvaluator) { // In Async environments we are going to have async predicates. There is none way to know // before hand so we need to evaluate all the predicates, verify for thenables, and finally, // define how to return the treatment (wrap result into a Promise or not). diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index bacd3b10..7f8db593 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -1,5 +1,5 @@ import { ENGINE_BUCKET } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { bucket } from '../../utils/murmur3/murmur3'; /** diff --git a/src/evaluator/condition/index.ts b/src/evaluator/condition/index.ts index 5cf1cac8..8b75eedd 100644 --- a/src/evaluator/condition/index.ts +++ b/src/evaluator/condition/index.ts @@ -3,8 +3,8 @@ import { thenable } from '../../utils/promise/thenable'; import * as LabelsConstants from '../../utils/labels'; import { MaybeThenable } from '../../dtos/types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { SplitKey, SplitKeyObject, Attributes } from '../../types'; +import { ILogger } from '../../types'; // Build Evaluation object if and only if matchingResult is true function match(log: ILogger, matchingResult: boolean, bucketingKey: string | undefined, seed: number, treatments: { getTreatmentFor: (x: number) => string }, label: string): IEvaluation | undefined { @@ -24,10 +24,10 @@ function match(log: ILogger, matchingResult: boolean, bucketingKey: string | und // Condition factory export function conditionContext(log: ILogger, matcherEvaluator: (...args: any) => MaybeThenable, treatments: { getTreatmentFor: (x: number) => string }, label: string, conditionType: 'ROLLOUT' | 'WHITELIST'): IEvaluator { - return function conditionEvaluator(key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) { + return function conditionEvaluator(key: SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: Attributes, splitEvaluator?: ISplitEvaluator) { // Whitelisting has more priority than traffic allocation, so we don't apply this filtering to those conditions. - if (conditionType === 'ROLLOUT' && !shouldApplyRollout(trafficAllocation as number, (key as SplitIO.SplitKeyObject).bucketingKey as string, trafficAllocationSeed as number)) { + if (conditionType === 'ROLLOUT' && !shouldApplyRollout(trafficAllocation as number, (key as SplitKeyObject).bucketingKey as string, trafficAllocationSeed as number)) { return { treatment: undefined, // treatment value is assigned later label: LabelsConstants.NOT_IN_SPLIT @@ -41,10 +41,10 @@ export function conditionContext(log: ILogger, matcherEvaluator: (...args: any) const matches = matcherEvaluator(key, attributes, splitEvaluator); if (thenable(matches)) { - return matches.then(result => match(log, result, (key as SplitIO.SplitKeyObject).bucketingKey, seed, treatments, label)); + return matches.then(result => match(log, result, (key as SplitKeyObject).bucketingKey, seed, treatments, label)); } - return match(log, matches, (key as SplitIO.SplitKeyObject).bucketingKey, seed, treatments, label); + return match(log, matches, (key as SplitKeyObject).bucketingKey, seed, treatments, label); }; } diff --git a/src/evaluator/index.ts b/src/evaluator/index.ts index 9f6cccf1..1360e9db 100644 --- a/src/evaluator/index.ts +++ b/src/evaluator/index.ts @@ -5,8 +5,8 @@ import { CONTROL } from '../utils/constants'; import { ISplit, MaybeThenable } from '../dtos/types'; import { IStorageAsync, IStorageSync } from '../storages/types'; import { IEvaluationResult } from './types'; -import { SplitIO } from '../types'; -import { ILogger } from '../logger/types'; +import { SplitKey, Attributes } from '../types'; +import { ILogger } from '../types'; const treatmentException = { treatment: CONTROL, @@ -24,9 +24,9 @@ function treatmentsException(splitNames: string[]) { export function evaluateFeature( log: ILogger, - key: SplitIO.SplitKey, + key: SplitKey, splitName: string, - attributes: SplitIO.Attributes | undefined, + attributes: Attributes | undefined, storage: IStorageSync | IStorageAsync, ): MaybeThenable { let stringifiedSplit; @@ -63,9 +63,9 @@ export function evaluateFeature( export function evaluateFeatures( log: ILogger, - key: SplitIO.SplitKey, + key: SplitKey, splitNames: string[], - attributes: SplitIO.Attributes | undefined, + attributes: Attributes | undefined, storage: IStorageSync | IStorageAsync, ): MaybeThenable> { let stringifiedSplits; @@ -90,8 +90,8 @@ export function evaluateFeatures( function getEvaluation( log: ILogger, stringifiedSplit: string | null, - key: SplitIO.SplitKey, - attributes: SplitIO.Attributes | undefined, + key: SplitKey, + attributes: Attributes | undefined, storage: IStorageSync | IStorageAsync, ): MaybeThenable { let evaluation: MaybeThenable = { @@ -126,8 +126,8 @@ function getEvaluations( log: ILogger, splitNames: string[], splits: Record, - key: SplitIO.SplitKey, - attributes: SplitIO.Attributes | undefined, + key: SplitKey, + attributes: Attributes | undefined, storage: IStorageSync | IStorageAsync, ): MaybeThenable> { const result: Record = {}; diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index 51326a91..df62047b 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_ALL } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function allMatcherContext(log: ILogger) { return function allMatcher(runtimeAttr: string): boolean { diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index 063e2a59..d6847b13 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -1,6 +1,6 @@ import { IBetweenMatcherData } from '../../dtos/types'; import { ENGINE_MATCHER_BETWEEN } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatcherData) /*: Function */ { return function betweenMatcher(runtimeAttr: number): boolean { diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index 821d8f98..9f40c4c9 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_BOOLEAN } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function booleanMatcherContext(log: ILogger, ruleAttr: boolean) /*: Function */ { return function booleanMatcher(runtimeAttr: boolean): boolean { diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index e52a9e85..ef45b805 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_CONTAINS_ALL } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { findIndex } from '../../utils/lang'; export function containsAllSetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index 6ab0b08c..f2e41f32 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_CONTAINS_ANY } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { findIndex } from '../../utils/lang'; export function containsAnySetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index b3dfe506..7c5a2193 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -1,5 +1,5 @@ import { isString } from '../../utils/lang'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { ENGINE_MATCHER_CONTAINS_STRING } from '../../logger/constants'; export function containsStringMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index 42040328..212d4e9b 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -1,6 +1,6 @@ import { IDependencyMatcherData, MaybeThenable } from '../../dtos/types'; import { IStorageAsync, IStorageSync } from '../../storages/types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { thenable } from '../../utils/promise/thenable'; import { IDependencyMatcherValue, IEvaluation, ISplitEvaluator } from '../types'; import { ENGINE_MATCHER_DEPENDENCY, ENGINE_MATCHER_DEPENDENCY_PRE } from '../../logger/constants'; diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index 019b1a19..1ec30358 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_EQUAL } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function equalToMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { return function equalToMatcher(runtimeAttr: number): boolean { diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index b36b1103..b1abcae7 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_EQUAL_TO_SET } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { findIndex } from '../../utils/lang'; export function equalToSetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index 6afdc9e1..61bd216f 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_ENDS_WITH } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { endsWith } from '../../utils/lang'; export function endsWithMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index 83d83e4e..63a35b46 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_GREATER } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { return function greaterThanEqualMatcher(runtimeAttr: number): boolean { diff --git a/src/evaluator/matchers/index.ts b/src/evaluator/matchers/index.ts index ecb195b4..7aacea95 100644 --- a/src/evaluator/matchers/index.ts +++ b/src/evaluator/matchers/index.ts @@ -17,7 +17,7 @@ import { booleanMatcherContext } from './boolean'; import { stringMatcherContext } from './string'; import { IStorageAsync, IStorageSync } from '../../storages/types'; import { IMatcher, IMatcherDto } from '../types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; const matchers = [ undefined, // UNDEFINED: 0, diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index b2ebeeb6..a54c38ef 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_LESS } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function lessThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: function */ { return function lessThanEqualMatcher(runtimeAttr: number): boolean { diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index 75385731..784fdcfb 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -1,5 +1,5 @@ import { findIndex } from '../../utils/lang'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { ENGINE_MATCHER_PART_OF } from '../../logger/constants'; export function partOfSetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index ad5ec30a..05590916 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -1,6 +1,6 @@ import { MaybeThenable } from '../../dtos/types'; import { ISegmentsCacheBase } from '../../storages/types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { thenable } from '../../utils/promise/thenable'; import { ENGINE_MATCHER_SEGMENT } from '../../logger/constants'; diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index 81e8bc48..5707a8f6 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_STRING_INVALID, ENGINE_MATCHER_STRING } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function stringMatcherContext(log: ILogger, ruleAttr: string) /*: Function */ { return function stringMatcher(runtimeAttr: string): boolean { diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index 7f014b20..f68f834c 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -1,5 +1,5 @@ import { ENGINE_MATCHER_STARTS_WITH } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { startsWith } from '../../utils/lang'; export function startsWithMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index 54fb35c8..504fa56c 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -1,5 +1,5 @@ import { setToArray, ISet } from '../../utils/lang/sets'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { ENGINE_MATCHER_WHITELIST } from '../../logger/constants'; export function whitelistMatcherContext(log: ILogger, ruleAttr: ISet) /*: Function */ { diff --git a/src/evaluator/parser/index.ts b/src/evaluator/parser/index.ts index 25c1e7f1..d297f161 100644 --- a/src/evaluator/parser/index.ts +++ b/src/evaluator/parser/index.ts @@ -9,8 +9,8 @@ import { thenable } from '../../utils/promise/thenable'; import { IEvaluator, IMatcherDto, ISplitEvaluator } from '../types'; import { ISplitCondition } from '../../dtos/types'; import { IStorageAsync, IStorageSync } from '../../storages/types'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { Attributes } from '../../types'; +import { ILogger } from '../../types'; export function parser(log: ILogger, conditions: ISplitCondition[], storage: IStorageSync | IStorageAsync): IEvaluator { let predicates = []; @@ -31,7 +31,7 @@ export function parser(log: ILogger, conditions: ISplitCondition[], storage: ISt const matcher = matcherFactory(log, matcherDto, storage); // Evaluator function. - return (key: string, attributes: SplitIO.Attributes | undefined, splitEvaluator: ISplitEvaluator) => { + return (key: string, attributes: Attributes | undefined, splitEvaluator: ISplitEvaluator) => { const value = sanitizeValue(log, key, matcherDto, attributes); const result = value !== undefined && matcher ? matcher(value, splitEvaluator) : false; diff --git a/src/evaluator/types.ts b/src/evaluator/types.ts index 54078b5b..9347b962 100644 --- a/src/evaluator/types.ts +++ b/src/evaluator/types.ts @@ -1,12 +1,12 @@ import { IBetweenMatcherData, IDependencyMatcherData, MaybeThenable } from '../dtos/types'; import { IStorageAsync, IStorageSync } from '../storages/types'; import { ISet } from '../utils/lang/sets'; -import { SplitIO } from '../types'; -import { ILogger } from '../logger/types'; +import { SplitKey, Attributes } from '../types'; +import { ILogger } from '../types'; export interface IDependencyMatcherValue { - key: SplitIO.SplitKey, - attributes?: SplitIO.Attributes + key: SplitKey, + attributes?: Attributes } export interface IMatcherDto { @@ -27,8 +27,8 @@ export interface IEvaluation { export type IEvaluationResult = IEvaluation & { treatment: string } -export type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync) => MaybeThenable +export type ISplitEvaluator = (log: ILogger, key: SplitKey, splitName: string, attributes: Attributes | undefined, storage: IStorageSync | IStorageAsync) => MaybeThenable -export type IEvaluator = (key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable +export type IEvaluator = (key: SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable export type IMatcher = (...args: any) => MaybeThenable diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index c564a68f..43f79848 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -1,10 +1,10 @@ -import { SplitIO } from '../../types'; +import { Attributes } from '../../types'; import { IMatcherDto } from '../types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { sanitize } from './sanitize'; import { ENGINE_VALUE, ENGINE_VALUE_NO_ATTRIBUTES, ENGINE_VALUE_INVALID } from '../../logger/constants'; -function parseValue(log: ILogger, key: string, attributeName: string | null, attributes?: SplitIO.Attributes) { +function parseValue(log: ILogger, key: string, attributeName: string | null, attributes?: Attributes) { let value = undefined; if (attributeName) { if (attributes) { @@ -23,7 +23,7 @@ function parseValue(log: ILogger, key: string, attributeName: string | null, att /** * Defines value to be matched (key / attribute). */ -export function sanitizeValue(log: ILogger, key: string, matcherDto: IMatcherDto, attributes?: SplitIO.Attributes) { +export function sanitizeValue(log: ILogger, key: string, matcherDto: IMatcherDto, attributes?: Attributes) { const attributeName = matcherDto.attribute; const valueToMatch = parseValue(log, key, attributeName, attributes); const sanitizedValue = sanitize(log, matcherDto.type, valueToMatch, matcherDto.dataType, attributes); diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index d12de8ed..c9980204 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -1,6 +1,6 @@ -import { SplitIO } from '../../types'; +import { Attributes } from '../../types'; import { IDependencyMatcherValue } from '../types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { isObject, uniq, toString, toNumber } from '../../utils/lang'; import { zeroSinceHH, zeroSinceSS } from '../convertions'; import { matcherTypes, matcherDataTypes } from '../matchers/matcherTypes'; @@ -41,7 +41,7 @@ function sanitizeBoolean(val: any): boolean | undefined { return undefined; } -function dependencyProcessor(sanitizedValue: string, attributes?: SplitIO.Attributes): IDependencyMatcherValue { +function dependencyProcessor(sanitizedValue: string, attributes?: Attributes): IDependencyMatcherValue { return { key: sanitizedValue, attributes @@ -69,7 +69,7 @@ function getProcessingFunction(matcherTypeID: number, dataType: string) { /** * Sanitize matcher value */ -export function sanitize(log: ILogger, matcherTypeID: number, value: string | number | boolean | Array | undefined, dataType: string, attributes?: SplitIO.Attributes) { +export function sanitize(log: ILogger, matcherTypeID: number, value: string | number | boolean | Array | undefined, dataType: string, attributes?: Attributes) { const processor = getProcessingFunction(matcherTypeID, dataType); let sanitizedValue: string | number | boolean | Array | IDependencyMatcherValue | undefined; diff --git a/src/integrations/ga/GaToSplit.ts b/src/integrations/ga/GaToSplit.ts index 35939dd8..85df41e4 100644 --- a/src/integrations/ga/GaToSplit.ts +++ b/src/integrations/ga/GaToSplit.ts @@ -8,9 +8,9 @@ import { validateKey, validateTrafficType, } from '../../utils/inputValidation'; -import { SplitIO } from '../../types'; +import { EventData } from '../../types'; import { Identity, GoogleAnalyticsToSplitOptions } from './types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { IIntegrationFactoryParams } from '../types'; const logPrefix = 'ga-to-split: '; @@ -67,7 +67,7 @@ const defaultMapping = { * @param {object} mapping */ function mapperBuilder(mapping: typeof defaultMapping) { - return function (model: UniversalAnalytics.Model): SplitIO.EventData { + return function (model: UniversalAnalytics.Model): EventData { const hitType: string = model.get('hitType'); // @ts-expect-error const eventTypeId = model.get(mapping.eventTypeId[hitType] || 'hitType'); @@ -133,7 +133,7 @@ export function validateIdentities(identities?: Identity[]) { * @param {EventData} data event data instance to validate. Precondition: data != undefined * @returns {boolean} Whether the data instance is a valid EventData or not. */ -export function validateEventData(log: ILogger, eventData: any): eventData is SplitIO.EventData { +export function validateEventData(log: ILogger, eventData: any): eventData is EventData { if (!validateEvent(log, eventData.eventTypeId, logNameMapper)) return false; @@ -251,10 +251,10 @@ export function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, params: IIn } // map hit into an EventData instance - let eventData: SplitIO.EventData = defaultMapper(model); + let eventData: EventData = defaultMapper(model); if (opts.mapper) { try { - eventData = opts.mapper(model, eventData as SplitIO.EventData); + eventData = opts.mapper(model, eventData as EventData); } catch (err) { log.warn(logPrefix + `custom mapper threw: ${err}`); return; diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index dd469676..46ce844b 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -1,10 +1,10 @@ /* eslint-disable no-undef */ import { uniq } from '../../utils/lang'; import { SPLIT_IMPRESSION, SPLIT_EVENT } from '../../utils/constants'; -import { SplitIO } from '../../types'; +import { IntegrationData, ImpressionData, EventData } from '../../types'; import { IIntegration } from '../types'; import { SplitToGoogleAnalyticsOptions } from './types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; const logPrefix = 'split-to-ga: '; const noGaWarning = '`ga` command queue not found.'; @@ -16,29 +16,29 @@ export class SplitToGa implements IIntegration { static defaultTrackerNames = ['']; private trackerNames: string[]; - private filter?: (data: SplitIO.IntegrationData) => boolean; - private mapper?: (data: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject; + private filter?: (data: IntegrationData) => boolean; + private mapper?: (data: IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject; private impressions: boolean | undefined; private events: boolean | undefined; private log: ILogger; // Default mapper function. - static defaultMapper({ type, payload }: SplitIO.IntegrationData): UniversalAnalytics.FieldsObject { + static defaultMapper({ type, payload }: IntegrationData): UniversalAnalytics.FieldsObject { switch (type) { case SPLIT_IMPRESSION: return { hitType: 'event', eventCategory: 'split-impression', - eventAction: 'Evaluate ' + (payload as SplitIO.ImpressionData).impression.feature, - eventLabel: 'Treatment: ' + (payload as SplitIO.ImpressionData).impression.treatment + '. Targeting rule: ' + (payload as SplitIO.ImpressionData).impression.label + '.', + eventAction: 'Evaluate ' + (payload as ImpressionData).impression.feature, + eventLabel: 'Treatment: ' + (payload as ImpressionData).impression.treatment + '. Targeting rule: ' + (payload as ImpressionData).impression.label + '.', nonInteraction: true, }; case SPLIT_EVENT: return { hitType: 'event', eventCategory: 'split-event', - eventAction: (payload as SplitIO.EventData).eventTypeId, - eventValue: (payload as SplitIO.EventData).value, + eventAction: (payload as EventData).eventTypeId, + eventValue: (payload as EventData).value, nonInteraction: true, }; } @@ -93,7 +93,7 @@ export class SplitToGa implements IIntegration { if (typeof SplitToGa.getGa() !== 'function') log.warn(logPrefix + `${noGaWarning} No hits will be sent until it is available.`); } - queue(data: SplitIO.IntegrationData) { + queue(data: IntegrationData) { // access ga command queue via `getGa` method, accounting for the possibility that // the global `ga` reference was not yet mutated by analytics.js. const ga = SplitToGa.getGa(); diff --git a/src/integrations/ga/__tests__/GaToSplit.spec.ts b/src/integrations/ga/__tests__/GaToSplit.spec.ts index 3c3196e9..47f3bb84 100644 --- a/src/integrations/ga/__tests__/GaToSplit.spec.ts +++ b/src/integrations/ga/__tests__/GaToSplit.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable no-undef */ import { IEventsCacheSync } from '../../../storages/types'; -import { SplitIO, ISettings } from '../../../types'; +import { ISettings, EventData } from '../../../types'; import { GaToSplit, validateIdentities, defaultPrefix, defaultMapper, validateEventData, fixEventTypeId } from '../GaToSplit'; import { gaMock, gaRemove, modelMock } from './gaMock'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; @@ -96,7 +96,7 @@ test('defaultMapper', () => { expect(defaultEvent.eventTypeId).toBe(expectedDefaultEvent.eventTypeId); // should return the corresponding default event instance for a given pageview hit expect(defaultEvent.value).toBe(expectedDefaultEvent.value); - expect(defaultEvent.properties).toEqual(expectedDefaultEvent.properties); + expect(defaultEvent.properties).toEqual(expectedDefaultEvent.properties); // @ts-ignore expect(initTimestamp <= defaultEvent.timestamp && defaultEvent.timestamp <= Date.now()).toBe(true); }); @@ -117,17 +117,17 @@ const fakeParams = { }; // Returns a new event by copying defaultEvent -function customMapper(model: UniversalAnalytics.Model, defaultEvent: SplitIO.EventData) { +function customMapper(model: UniversalAnalytics.Model, defaultEvent: EventData) { return { ...defaultEvent, properties: { ...defaultEvent.properties, someProp: 'someProp' } }; } // Updates defaultEvent -function customMapper2(model: UniversalAnalytics.Model, defaultEvent: SplitIO.EventData) { +function customMapper2(model: UniversalAnalytics.Model, defaultEvent: EventData) { // @ts-ignore. The defaultEvent has a property value, that might be empty depending on the hitType defaultEvent.properties['someProp2'] = 'someProp2'; return defaultEvent; } // Updates defaultEvent adding a `key` and `TT`, to assert that `identities` plugin param is ignored. -function customMapper3(model: UniversalAnalytics.Model, defaultEvent: SplitIO.EventData) { +function customMapper3(model: UniversalAnalytics.Model, defaultEvent: EventData) { defaultEvent.key = 'someKey'; defaultEvent.trafficTypeName = 'someTT'; return defaultEvent; diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index d05e4bab..73acface 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -1,4 +1,4 @@ -import { SplitIO } from '../../../types'; +import { IntegrationData, ImpressionData, EventData } from '../../../types'; import { SPLIT_IMPRESSION, SPLIT_EVENT } from '../../../utils/constants'; // Mocks @@ -8,7 +8,7 @@ import { gaMock, gaRemove } from './gaMock'; // Test target import { SplitToGa } from '../SplitToGa'; -const fakeImpressionPayload: SplitIO.ImpressionData = { +const fakeImpressionPayload: ImpressionData = { impression: { feature: 'hierarchical_splits_test', keyName: 'nicolas@split.io', @@ -23,7 +23,7 @@ const fakeImpressionPayload: SplitIO.ImpressionData = { hostname: 'hostname', sdkLanguageVersion: 'version', }; -const fakeImpression: SplitIO.IntegrationData = { +const fakeImpression: IntegrationData = { type: SPLIT_IMPRESSION, payload: fakeImpressionPayload, }; @@ -35,7 +35,7 @@ const defaultImpressionFieldsObject: UniversalAnalytics.FieldsObject = { nonInteraction: true }; -const fakeEventPayload: SplitIO.EventData = { +const fakeEventPayload: EventData = { eventTypeId: 'eventTypeId', trafficTypeName: 'trafficTypeName', value: 0, @@ -43,7 +43,7 @@ const fakeEventPayload: SplitIO.EventData = { key: 'key', properties: {}, }; -const fakeEvent: SplitIO.IntegrationData = { +const fakeEvent: IntegrationData = { type: SPLIT_EVENT, payload: fakeEventPayload, }; @@ -120,7 +120,7 @@ describe('SplitToGa', () => { /** Custom behaviour **/ // Custom filter - function customFilter(data: SplitIO.IntegrationData) { + function customFilter(data: IntegrationData) { return data.type === SPLIT_EVENT; } // Custom mapper that returns a new FieldsObject instance @@ -149,7 +149,7 @@ describe('SplitToGa', () => { expect(ga).toBeCalledTimes(2); // Custom mapper that returns the default FieldsObject - function customMapper2(data: SplitIO.IntegrationData, defaultFieldsObject: UniversalAnalytics.FieldsObject) { + function customMapper2(data: IntegrationData, defaultFieldsObject: UniversalAnalytics.FieldsObject) { return defaultFieldsObject; } const instance3 = new SplitToGa(loggerMock, { diff --git a/src/integrations/ga/types.ts b/src/integrations/ga/types.ts index dfa5f11e..7af90ad1 100644 --- a/src/integrations/ga/types.ts +++ b/src/integrations/ga/types.ts @@ -1,4 +1,4 @@ -import { SplitIO } from '../../types'; +import { IntegrationData, EventData } from '../../types'; /** * A pair of user key and it's trafficType, required for tracking valid Split events. @@ -41,7 +41,7 @@ export interface GoogleAnalyticsToSplitOptions { * return defaultMapping; * }` */ - mapper?: (model: UniversalAnalytics.Model, defaultMapping: SplitIO.EventData) => SplitIO.EventData, + mapper?: (model: UniversalAnalytics.Model, defaultMapping: EventData) => EventData, /** * Optional prefix for EventTypeId, to prevent any kind of data collision between events. * @property {string} prefix @@ -97,7 +97,7 @@ export interface SplitToGoogleAnalyticsOptions { * For example, the following filter allows to track only impressions, equivalent to setting events to false: * `(data) => data.type === 'IMPRESSION'` */ - filter?: (data: SplitIO.IntegrationData) => boolean, + filter?: (data: IntegrationData) => boolean, /** * Optional function useful when you need to modify the GA hit before sending it. * This function is invoked with two arguments: @@ -128,7 +128,7 @@ export interface SplitToGoogleAnalyticsOptions { * nonInteraction: true, * }` */ - mapper?: (data: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject, + mapper?: (data: IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject, /** * List of tracker names to send the hit. An empty string represents the default tracker. * If not provided, hits are only sent to default tracker. diff --git a/src/integrations/pluggable.ts b/src/integrations/pluggable.ts index df4ccd21..333b14ea 100644 --- a/src/integrations/pluggable.ts +++ b/src/integrations/pluggable.ts @@ -1,5 +1,5 @@ import { SPLIT_IMPRESSION, SPLIT_EVENT } from '../utils/constants'; -import { SplitIO } from '../types'; +import { ImpressionData, EventData } from '../types'; import { IIntegration, IIntegrationManager, IIntegrationFactoryParams } from './types'; /** @@ -29,10 +29,10 @@ export function pluggableIntegrationsManagerFactory( // Exception safe methods: each integration module is responsable for handling errors return { - handleImpression(impressionData: SplitIO.ImpressionData) { + handleImpression(impressionData: ImpressionData) { listeners.forEach(listener => listener.queue({ type: SPLIT_IMPRESSION, payload: impressionData })); }, - handleEvent(eventData: SplitIO.EventData) { + handleEvent(eventData: EventData) { listeners.forEach(listener => listener.queue({ type: SPLIT_EVENT, payload: eventData })); } }; diff --git a/src/integrations/types.ts b/src/integrations/types.ts index 0c050879..4048a8d1 100644 --- a/src/integrations/types.ts +++ b/src/integrations/types.ts @@ -1,9 +1,9 @@ import { IEventsCacheBase } from '../storages/types'; import { IEventsHandler, IImpressionsHandler } from '../trackers/types'; -import { ISettings, SplitIO } from '../types'; +import { ISettings, IntegrationData } from '../types'; export interface IIntegration { - queue(data: SplitIO.IntegrationData): void + queue(data: IntegrationData): void } export type IIntegrationManager = IEventsHandler & IImpressionsHandler; diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 93085c25..3b45c3ff 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -37,7 +37,7 @@ test('SPLIT LOGGER / Logger class shape', () => { expect(typeof logger.setLogLevel).toBe('function'); // instance.setLogLevel should be a method. }); -const LOG_LEVELS_IN_ORDER = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; +const LOG_LEVELS_IN_ORDER: LogLevel[] = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; /* Utility function to avoid repeating too much code */ function testLogLevels(levelToTest: LogLevel) { // Builds the expected message. diff --git a/src/logger/index.ts b/src/logger/index.ts index 4fba156a..12b33bb6 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -1,10 +1,10 @@ import { objectAssign } from '../utils/lang/objectAssign'; -import { ILoggerOptions, ILogger } from './types'; +import { ILoggerOptions } from './types'; import { find } from '../utils/lang'; -import { LogLevel } from '../types'; +import { LogLevel, ILogger, ILoggerAPI } from '../types'; import { IMap, _Map } from '../utils/lang/maps'; -export const LogLevels: { [level: string]: LogLevel } = { +export const LogLevels: ILoggerAPI['LogLevel'] = { DEBUG: 'DEBUG', INFO: 'INFO', WARN: 'WARN', diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 41c3635a..9e9c8604 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -1,6 +1,5 @@ import { LogLevels, isLogLevelString } from './index'; -import { ILoggerAPI } from '../types'; -import { ILogger } from './types'; +import { ILoggerAPI, ILogger } from '../types'; import { ERROR_LOGLEVEL_INVALID } from './constants'; /** diff --git a/src/logger/types.ts b/src/logger/types.ts index 79ec1b07..d5361598 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -5,19 +5,3 @@ export interface ILoggerOptions { logLevel?: LogLevel, showLevel?: boolean, // @TODO remove this param eventually since it is not being set `false` anymore } - -export interface ILogger { - setLogLevel(logLevel: LogLevel): void - - debug(msg: any): void - debug(msg: string | number, args?: any[]): void - - info(msg: any): void - info(msg: string | number, args?: any[]): void - - warn(msg: any): void - warn(msg: string | number, args?: any[]): void - - error(msg: any): void - error(msg: string | number, args?: any[]): void -} diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index c137e040..edb6c6bd 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -4,7 +4,7 @@ import { readinessManagerFactory } from './readinessManager'; import { ISdkReadinessManager } from './types'; import { IEventEmitter } from '../types'; import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants'; -import { ILogger } from '../logger/types'; +import { ILogger } from '../types'; import { ERROR_CLIENT_LISTENER, CLIENT_READY_FROM_CACHE, CLIENT_READY, CLIENT_NO_LISTENER } from '../logger/constants'; const NEW_LISTENER_EVENT = 'newListener'; diff --git a/src/readiness/types.ts b/src/readiness/types.ts index 93986f60..3f59a322 100644 --- a/src/readiness/types.ts +++ b/src/readiness/types.ts @@ -1,4 +1,4 @@ -import { IEventEmitter, IStatusInterface } from '../types'; +import { IEventEmitter, IStatusInterface, Event } from '../types'; /** Splits data emitter */ @@ -28,15 +28,8 @@ export interface ISegmentsEventEmitter extends IEventEmitter { /** Readiness emitter */ -export type SDK_READY_TIMED_OUT = 'init::timeout' -export type SDK_READY = 'init::ready' -export type SDK_READY_FROM_CACHE = 'init::cache-ready' -export type SDK_UPDATE = 'state::update' -export type SDK_DESTROY = 'state::destroy' -export type IReadinessEvent = SDK_READY_TIMED_OUT | SDK_READY | SDK_READY_FROM_CACHE | SDK_UPDATE | SDK_DESTROY - export interface IReadinessEventEmitter extends IEventEmitter { - emit(event: IReadinessEvent, ...args: any[]): boolean + emit(event: Event, ...args: any[]): boolean } /** Readiness manager */ diff --git a/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts b/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts index f5c49f96..fbc38a63 100644 --- a/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts +++ b/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts @@ -74,8 +74,8 @@ describe('ATTRIBUTES DECORATION / validation', () => { }); test('Should return false if it is an invalid attributes map', () => { - expect(client.setAttribute('', 'attributeValue')).toEqual(false); // It should be invalid if the attribute key is not a string - expect(client.setAttribute('attributeKey1', new Date())).toEqual(false); // It should be invalid if the attribute value is not a String, Number, Boolean or Lists. + expect(client.setAttribute('', 'attributeValue')).toEqual(false); // @ts-ignore It should be invalid if the attribute key is not a string + expect(client.setAttribute('attributeKey1', new Date())).toEqual(false); // @ts-ignore It should be invalid if the attribute value is not a String, Number, Boolean or Lists. expect(client.setAttribute('attributeKey2', { 'some': 'object' })).toEqual(false); // It should be invalid if the attribute value is not a String, Number, Boolean or Lists. expect(client.setAttribute('attributeKey3', Infinity)).toEqual(false); // It should be invalid if the attribute value is not a String, Number, Boolean or Lists. diff --git a/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts b/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts index dbe57ec9..bba633eb 100644 --- a/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts +++ b/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import { sdkClientMethodCSFactory as sdkClientMethodCSWithTTFactory } from '../sdkClientMethodCSWithTT'; import { sdkClientMethodCSFactory } from '../sdkClientMethodCS'; import { assertClientApi } from './testUtils'; @@ -80,7 +81,6 @@ describe('sdkClientMethodCSFactory', () => { ]; test.each(testTargets)('main client', (sdkClientMethodCSFactory) => { - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); // should return a function @@ -106,7 +106,6 @@ describe('sdkClientMethodCSFactory', () => { test.each(testTargets)('multiple clients', async (sdkClientMethodCSFactory, ignoresTT) => { - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); // calling the function with a diferent key than settings, should return a new client instance @@ -151,7 +150,6 @@ describe('sdkClientMethodCSFactory', () => { test.each(testTargets)('return main client instance if called with same key', (sdkClientMethodCSFactory) => { params.settings = settingsWithKey; - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); expect(sdkClientMethod()).toBe(sdkClientMethod(settingsWithKey.core.key)); @@ -164,7 +162,6 @@ describe('sdkClientMethodCSFactory', () => { test.each(testTargets)('return main client instance if called with same key and TT', (sdkClientMethodCSFactory) => { params.settings = settingsWithKeyAndTT; - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); expect(sdkClientMethod()).toBe(sdkClientMethod(settingsWithKeyAndTT.core.key, settingsWithKeyAndTT.core.trafficType)); @@ -175,9 +172,7 @@ describe('sdkClientMethodCSFactory', () => { }); test.each(testTargets)('return main client instance if called with same key object', (sdkClientMethodCSFactory) => { - // @ts-expect-error params.settings = settingsWithKeyObject; - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); expect(sdkClientMethod()).toBe(sdkClientMethod({ matchingKey: settingsWithKeyObject.core.key.matchingKey, bucketingKey: settingsWithKeyObject.core.key.bucketingKey })); @@ -188,7 +183,6 @@ describe('sdkClientMethodCSFactory', () => { }); test.each(testTargets)('return same client instance if called with same key or traffic type (input validation)', (sdkClientMethodCSFactory, ignoresTT) => { - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); const clientInstance = sdkClientMethod('key', 'tt'); @@ -211,14 +205,12 @@ describe('sdkClientMethodCSFactory', () => { }); test.each(testTargets)('invalid calls throw an error', (sdkClientMethodCSFactory, ignoresTT) => { - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); expect(() => sdkClientMethod({ matchingKey: settingsWithKey.core.key, bucketingKey: undefined })).toThrow('Shared Client needs a valid key.'); if (!ignoresTT) expect(() => sdkClientMethod('valid-key', ['invalid-TT'])).toThrow('Shared Client needs a valid traffic type or no traffic type at all.'); }); test.each(testTargets)('attributes binding - main client', (sdkClientMethodCSFactory) => { - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); // should return a function @@ -272,7 +264,6 @@ describe('sdkClientMethodCSFactory', () => { test.each(testTargets)('attributes binding - shared clients', (sdkClientMethodCSFactory) => { - // @ts-expect-error const sdkClientMethod = sdkClientMethodCSFactory(params); // should return a function diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index 3d3f0fd6..abbe9b71 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -6,18 +6,18 @@ import { validateTrafficTypeExistance } from '../utils/inputValidation/trafficTy import { SDK_NOT_READY } from '../utils/labels'; import { CONTROL, TREATMENT, TREATMENTS, TREATMENT_WITH_CONFIG, TREATMENTS_WITH_CONFIG, TRACK } from '../utils/constants'; import { IEvaluationResult } from '../evaluator/types'; -import { SplitIO, ImpressionDTO } from '../types'; +import { SplitKey, Attributes,ImpressionDTO, Treatment, TreatmentWithConfig, Properties, EventData } from '../types'; import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants'; import { ISdkFactoryContext } from '../sdkFactory/types'; /** * Creator of base client with getTreatments and track methods. */ -export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | SplitIO.IAsyncClient { +export function clientFactory(params: ISdkFactoryContext) { const { sdkReadinessManager: { readinessManager }, storage, settings, impressionsTracker, eventTracker, telemetryTracker } = params; const { log, mode } = settings; - function getTreatment(key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, withConfig = false) { + function getTreatment(key: SplitKey, splitName: string, attributes: Attributes | undefined, withConfig = false) { const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENT_WITH_CONFIG : TREATMENT); const wrapUp = (evaluationResult: IEvaluationResult) => { @@ -34,16 +34,16 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl return thenable(evaluation) ? evaluation.then((res) => wrapUp(res)) : wrapUp(evaluation); } - function getTreatmentWithConfig(key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined) { + function getTreatmentWithConfig(key: SplitKey, splitName: string, attributes: Attributes | undefined) { return getTreatment(key, splitName, attributes, true); } - function getTreatments(key: SplitIO.SplitKey, splitNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false) { + function getTreatments(key: SplitKey, splitNames: string[], attributes: Attributes | undefined, withConfig = false) { const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENTS_WITH_CONFIG : TREATMENTS); const wrapUp = (evaluationResults: Record) => { const queue: ImpressionDTO[] = []; - const treatments: Record = {}; + const treatments: Record = {}; Object.keys(evaluationResults).forEach(splitName => { treatments[splitName] = processEvaluation(evaluationResults[splitName], splitName, key, attributes, withConfig, `getTreatments${withConfig ? 'withConfig' : ''}`, queue); }); @@ -58,7 +58,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations); } - function getTreatmentsWithConfig(key: SplitIO.SplitKey, splitNames: string[], attributes: SplitIO.Attributes | undefined) { + function getTreatmentsWithConfig(key: SplitKey, splitNames: string[], attributes: Attributes | undefined) { return getTreatments(key, splitNames, attributes, true); } @@ -66,12 +66,12 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl function processEvaluation( evaluation: IEvaluationResult, splitName: string, - key: SplitIO.SplitKey, - attributes: SplitIO.Attributes | undefined, + key: SplitKey, + attributes: Attributes | undefined, withConfig: boolean, invokingMethodName: string, queue: ImpressionDTO[] - ): SplitIO.Treatment | SplitIO.TreatmentWithConfig { + ): Treatment | TreatmentWithConfig { const isSdkReady = readinessManager.isReady() || readinessManager.isReadyFromCache(); const matchingKey = getMatching(key); const bucketingKey = getBucketing(key); @@ -107,12 +107,12 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl return treatment; } - function track(key: SplitIO.SplitKey, trafficTypeName: string, eventTypeId: string, value?: number, properties?: SplitIO.Properties, size = 1024) { + function track(key: SplitKey, trafficTypeName: string, eventTypeId: string, value?: number, properties?: Properties, size = 1024) { const stopTelemetryTracker = telemetryTracker.trackEval(TRACK); const matchingKey = getMatching(key); const timestamp = Date.now(); - const eventData: SplitIO.EventData = { + const eventData: EventData = { eventTypeId, trafficTypeName, value, @@ -144,5 +144,5 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl getTreatmentsWithConfig, track, isClientSide: false - } as SplitIO.IClient | SplitIO.IAsyncClient; + }; } diff --git a/src/sdkClient/clientAttributesDecoration.ts b/src/sdkClient/clientAttributesDecoration.ts index 8d160108..a001fda5 100644 --- a/src/sdkClient/clientAttributesDecoration.ts +++ b/src/sdkClient/clientAttributesDecoration.ts @@ -1,13 +1,13 @@ import { AttributesCacheInMemory } from '../storages/inMemory/AttributesCacheInMemory'; import { validateAttributesDeep } from '../utils/inputValidation/attributes'; -import { SplitIO } from '../types'; -import { ILogger } from '../logger/types'; +import { Attributes, AttributeType, IAsyncClientSS, IClientSS, Properties, SplitKey } from '../types'; +import { ILogger } from '../types'; import { objectAssign } from '../utils/lang/objectAssign'; /** * Add in memory attributes storage methods and combine them with any attribute received from the getTreatment/s call */ -export function clientAttributesDecoration(log: ILogger, client: TClient) { +export function clientAttributesDecoration(log: ILogger, client: IClientSS | IAsyncClientSS) { const attributeStorage = new AttributesCacheInMemory(); @@ -18,27 +18,27 @@ export function clientAttributesDecoration 0) { return objectAssign({}, storedAttributes, maybeAttributes); @@ -57,10 +57,10 @@ export function clientAttributesDecoration = {}; attribute[attributeName] = attributeValue; if (!validateAttributesDeep(log, attribute, 'setAttribute')) return false; @@ -85,7 +85,7 @@ export function clientAttributesDecoration) { + setAttributes(attributes: Record) { if (!validateAttributesDeep(log, attributes, 'setAttributes')) return false; return attributeStorage.setAttributes(attributes); }, @@ -95,7 +95,7 @@ export function clientAttributesDecoration { + getAttributes(): Record { return attributeStorage.getAll(); }, diff --git a/src/sdkClient/clientCS.ts b/src/sdkClient/clientCS.ts index c66d1e04..a305de35 100644 --- a/src/sdkClient/clientCS.ts +++ b/src/sdkClient/clientCS.ts @@ -1,6 +1,5 @@ import { objectAssign } from '../utils/lang/objectAssign'; -import { ILogger } from '../logger/types'; -import { SplitIO } from '../types'; +import { IClientSS, IClientWithKey, ILogger, SplitKey } from '../types'; import { clientAttributesDecoration } from './clientAttributesDecoration'; @@ -11,7 +10,7 @@ import { clientAttributesDecoration } from './clientAttributesDecoration'; * @param key validated split key * @param trafficType validated traffic type */ -export function clientCSDecorator(log: ILogger, client: SplitIO.IClient, key: SplitIO.SplitKey, trafficType?: string): SplitIO.ICsClient { +export function clientCSDecorator(log: ILogger, client: IClientSS, key: SplitKey, trafficType?: string) { let clientCS = clientAttributesDecoration(log, client); @@ -26,5 +25,5 @@ export function clientCSDecorator(log: ILogger, client: SplitIO.IClient, key: Sp track: trafficType ? clientCS.track.bind(clientCS, key, trafficType) : clientCS.track.bind(clientCS, key), isClientSide: true - }) as SplitIO.ICsClient; + }) as IClientWithKey; } diff --git a/src/sdkClient/clientInputValidation.ts b/src/sdkClient/clientInputValidation.ts index de9f3594..ce8ab7c3 100644 --- a/src/sdkClient/clientInputValidation.ts +++ b/src/sdkClient/clientInputValidation.ts @@ -15,14 +15,15 @@ import { startsWith } from '../utils/lang'; import { CONTROL, CONTROL_WITH_CONFIG } from '../utils/constants'; import { IReadinessManager } from '../readiness/types'; import { MaybeThenable } from '../dtos/types'; -import { ISettings, SplitIO } from '../types'; +import { ISettings, SplitKey, Treatments, TreatmentsWithConfig, Properties, Attributes, IClientSS, IAsyncClientSS } from '../types'; import { isStorageSync } from '../trackers/impressionObserver/utils'; +import { clientFactory } from './client'; /** * Decorator that validates the input before actually executing the client methods. * We should "guard" the client here, while not polluting the "real" implementation of those methods. */ -export function clientInputValidationDecorator(settings: ISettings, client: TClient, readinessManager: IReadinessManager): TClient { +export function clientInputValidationDecorator(settings: ISettings, client: ReturnType, readinessManager: IReadinessManager): IClientSS | IAsyncClientSS { const log = settings.log; const isSync = isStorageSync(settings); @@ -30,7 +31,7 @@ export function clientInputValidationDecorator res[split] = CONTROL); return wrapResult(res); } } - function getTreatmentsWithConfig(maybeKey: SplitIO.SplitKey, maybeSplits: string[], maybeAttributes?: SplitIO.Attributes) { + function getTreatmentsWithConfig(maybeKey: SplitKey, maybeSplits: string[], maybeAttributes?: Attributes) { const params = validateEvaluationParams(maybeKey, maybeSplits, maybeAttributes, 'getTreatmentsWithConfig'); if (params.valid) { - return client.getTreatmentsWithConfig(params.key as SplitIO.SplitKey, params.splitOrSplits as string[], params.attributes as SplitIO.Attributes | undefined); + return client.getTreatmentsWithConfig(params.key as SplitKey, params.splitOrSplits as string[], params.attributes as Attributes | undefined); } else { - const res: SplitIO.TreatmentsWithConfig = {}; + const res: TreatmentsWithConfig = {}; if (params.splitOrSplits) (params.splitOrSplits as string[]).forEach(split => res[split] = objectAssign({}, CONTROL_WITH_CONFIG)); return wrapResult(res); } } - function track(maybeKey: SplitIO.SplitKey, maybeTT: string, maybeEvent: string, maybeEventValue?: number, maybeProperties?: SplitIO.Properties) { + function track(maybeKey: SplitKey, maybeTT: string, maybeEvent: string, maybeEventValue?: number, maybeProperties?: Properties) { const key = validateKey(log, maybeKey, 'track'); const tt = validateTrafficType(log, maybeTT, 'track'); const event = validateEvent(log, maybeEvent, 'track'); @@ -120,5 +121,5 @@ export function clientInputValidationDecorator SplitIO.IClient | SplitIO.IAsyncClient { +export function sdkClientMethodFactory(params: ISdkFactoryContext): () => IClientSS | IAsyncClientSS { const log = params.settings.log; const clientInstance = sdkClientFactory(params); diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index 284c59ae..d5835e0d 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -1,5 +1,5 @@ import { clientCSDecorator } from './clientCS'; -import { SplitIO } from '../types'; +import { IClientSS, IClientWithKey, SplitKey } from '../types'; import { validateKey } from '../utils/inputValidation/key'; import { getMatching, keyParser } from '../utils/key'; import { sdkClientFactory } from './sdkClient'; @@ -9,7 +9,7 @@ import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } import { SDK_SEGMENTS_ARRIVED } from '../readiness/constants'; import { ISdkFactoryContext } from '../sdkFactory/types'; -function buildInstanceId(key: SplitIO.SplitKey) { +function buildInstanceId(key: SplitKey) { // @ts-ignore return `${key.matchingKey ? key.matchingKey : key}-${key.bucketingKey ? key.bucketingKey : key}-`; } @@ -20,23 +20,23 @@ const method = 'Client instantiation'; * Factory of client method for the client-side API variant where TT is ignored and thus * clients don't have a binded TT for the track method. */ -export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey) => SplitIO.ICsClient { +export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitKey) => IClientWithKey { const { storage, syncManager, sdkReadinessManager, settings: { core: { key }, startup: { readyTimeout }, log } } = params; const mainClientInstance = clientCSDecorator( log, - sdkClientFactory(params) as SplitIO.IClient, - key + sdkClientFactory(params) as IClientSS, + key! ); - const parsedDefaultKey = keyParser(key); + const parsedDefaultKey = keyParser(key!); const defaultInstanceId = buildInstanceId(parsedDefaultKey); // Cache instances created per factory. - const clientInstances: Record = {}; + const clientInstances: Record = {}; clientInstances[defaultInstanceId] = mainClientInstance; - return function client(key?: SplitIO.SplitKey) { + return function client(key?: SplitKey) { if (key === undefined) { log.debug(RETRIEVE_CLIENT_DEFAULT); return mainClientInstance; @@ -76,7 +76,7 @@ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: Spl storage: sharedStorage || storage, syncManager: sharedSyncManager, signalListener: undefined, // only the main client "destroy" method stops the signal listener - }), true) as SplitIO.IClient, + }), true) as IClientSS, validKey ); diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index 7abb36d8..b2567b07 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -1,5 +1,5 @@ import { clientCSDecorator } from './clientCS'; -import { SplitIO } from '../types'; +import { IClientSS, IClientWithKey, SplitKey } from '../types'; import { validateKey } from '../utils/inputValidation/key'; import { validateTrafficType } from '../utils/inputValidation/trafficType'; import { getMatching, keyParser } from '../utils/key'; @@ -10,7 +10,7 @@ import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } import { SDK_SEGMENTS_ARRIVED } from '../readiness/constants'; import { ISdkFactoryContext } from '../sdkFactory/types'; -function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) { +function buildInstanceId(key: SplitKey, trafficType?: string) { // @ts-ignore return `${key.matchingKey ? key.matchingKey : key}-${key.bucketingKey ? key.bucketingKey : key}-${trafficType !== undefined ? trafficType : ''}`; } @@ -22,24 +22,24 @@ const method = 'Client instantiation'; * where clients can have a binded TT for the track method, which is provided via the settings * (default client) or the client method (shared clients). */ -export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey, trafficType?: string) => SplitIO.ICsClient { +export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitKey, trafficType?: string) => IClientWithKey { const { storage, syncManager, sdkReadinessManager, settings: { core: { key, trafficType }, startup: { readyTimeout }, log } } = params; const mainClientInstance = clientCSDecorator( log, - sdkClientFactory(params) as SplitIO.IClient, - key, + sdkClientFactory(params) as IClientSS, + key!, trafficType ); - const parsedDefaultKey = keyParser(key); + const parsedDefaultKey = keyParser(key!); const defaultInstanceId = buildInstanceId(parsedDefaultKey, trafficType); // Cache instances created per factory. - const clientInstances: Record = {}; + const clientInstances: Record = {}; clientInstances[defaultInstanceId] = mainClientInstance; - return function client(key?: SplitIO.SplitKey, trafficType?: string) { + return function client(key?: SplitKey, trafficType?: string) { if (key === undefined) { log.debug(RETRIEVE_CLIENT_DEFAULT); return mainClientInstance; @@ -86,7 +86,7 @@ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: Spl storage: sharedStorage || storage, syncManager: sharedSyncManager, signalListener: undefined, // only the main client "destroy" method stops the signal listener - }), true) as SplitIO.IClient, + }), true) as IClientSS, validKey, validTrafficType ); diff --git a/src/sdkFactory/__tests__/index.spec.ts b/src/sdkFactory/__tests__/index.spec.ts index 185fccb4..4b06ae13 100644 --- a/src/sdkFactory/__tests__/index.spec.ts +++ b/src/sdkFactory/__tests__/index.spec.ts @@ -1,7 +1,7 @@ import { ISdkFactoryParams } from '../types'; import { sdkFactory } from '../index'; import { fullSettings } from '../../utils/settingsValidation/__tests__/settings.mocks'; -import { SplitIO } from '../../types'; +import { IBasicSDK } from '../../types'; import { EventEmitter } from '../../utils/MinEvents'; /** Mocks */ @@ -58,7 +58,7 @@ const fullParamsForSyncSDK = { /** End Mocks */ -function assertSdkApi(sdk: SplitIO.IAsyncSDK | SplitIO.ISDK | SplitIO.ICsSDK, params: any) { +function assertSdkApi(sdk: IBasicSDK, params: any) { expect(sdk.Logger).toBe(loggerApiMock); expect(sdk.settings).toBe(params.settings); expect(sdk.client).toBe(params.sdkClientMethodFactory.mock.results[0].value); diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 9bba6f95..8f002d85 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -4,7 +4,7 @@ import { impressionsTrackerFactory } from '../trackers/impressionsTracker'; import { eventTrackerFactory } from '../trackers/eventTracker'; import { telemetryTrackerFactory } from '../trackers/telemetryTracker'; import { IStorageFactoryParams } from '../storages/types'; -import { SplitIO } from '../types'; +import { IBasicSDK } from '../types'; import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; @@ -17,7 +17,7 @@ import { objectAssign } from '../utils/lang/objectAssign'; /** * Modular SDK factory */ -export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.ISDK | SplitIO.IAsyncSDK { +export function sdkFactory(params: ISdkFactoryParams): IBasicSDK { const { settings, platform, storageFactory, splitApiFactory, extraProps, syncManagerFactory, SignalListener, impressionsObserverFactory, diff --git a/src/sdkFactory/types.ts b/src/sdkFactory/types.ts index de8abe3f..7263920c 100644 --- a/src/sdkFactory/types.ts +++ b/src/sdkFactory/types.ts @@ -1,13 +1,13 @@ import { IIntegrationManager, IIntegrationFactoryParams } from '../integrations/types'; import { ISignalListener } from '../listeners/types'; -import { ILogger } from '../logger/types'; +import { IAsyncClientSS, IAsyncManager, IClientSS, IClientWithKey, ILogger, IManager, SplitKey } from '../types'; import { IReadinessManager, ISdkReadinessManager } from '../readiness/types'; import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types'; import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types'; import { ISyncManager } from '../sync/types'; import { IImpressionObserver } from '../trackers/impressionObserver/types'; import { IImpressionsTracker, IEventTracker, ITelemetryTracker } from '../trackers/types'; -import { SplitIO, ISettings, IEventEmitter } from '../types'; +import { ISettings, IEventEmitter } from '../types'; /** * Environment related dependencies. @@ -90,11 +90,11 @@ export interface ISdkFactoryParams { log: ILogger, splits: ISplitsCacheSync | ISplitsCacheAsync, sdkReadinessManager: ISdkReadinessManager - ) => SplitIO.IManager | SplitIO.IAsyncManager, + ) => IManager | IAsyncManager, // Sdk client method factory (ISDK::client method). // It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`). - sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient)) + sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): IClientWithKey; (key: SplitKey, trafficType?: string | undefined): IClientWithKey; } | (() => IClientSS) | (() => IAsyncClientSS)) // Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed. // Pass only if `syncManager` (used by Node listener) and `splitApi` (used by Browser listener) are passed. diff --git a/src/sdkManager/index.ts b/src/sdkManager/index.ts index e0ec5024..68ef2c5a 100644 --- a/src/sdkManager/index.ts +++ b/src/sdkManager/index.ts @@ -5,8 +5,8 @@ import { validateSplit, validateSplitExistance, validateIfNotDestroyed, validate import { ISplitsCacheAsync, ISplitsCacheSync } from '../storages/types'; import { ISdkReadinessManager } from '../readiness/types'; import { ISplit } from '../dtos/types'; -import { SplitIO } from '../types'; -import { ILogger } from '../logger/types'; +import { IAsyncManager, IManager, SplitView } from '../types'; +import { ILogger } from '../types'; function collectTreatments(splitObject: ISplit) { const conditions = splitObject.conditions; @@ -18,7 +18,7 @@ function collectTreatments(splitObject: ISplit) { return allTreatmentsCondition ? allTreatmentsCondition.partitions.map(v => v.treatment) : []; } -function objectToView(json: string | null): SplitIO.SplitView | null { +function objectToView(json: string | null): SplitView | null { let splitObject: ISplit | null; try { @@ -41,7 +41,7 @@ function objectToView(json: string | null): SplitIO.SplitView | null { } function objectsToViews(jsons: string[]) { - let views: SplitIO.SplitView[] = []; + let views: SplitView[] = []; jsons.forEach(split => { const view = objectToView(split); @@ -55,7 +55,7 @@ export function sdkManagerFactory = {}; + private attributesCache: Record = {}; /** * Create or update the value for the given attribute - * + * * @param {string} attributeName attribute name * @param {Object} attributeValue attribute value - * @returns {boolean} the attribute was stored + * @returns {boolean} the attribute was stored */ - setAttribute(attributeName: string, attributeValue: Object): boolean { + setAttribute(attributeName: string, attributeValue: AttributeType): boolean { this.attributesCache[attributeName] = attributeValue; return true; } /** * Retrieves the value of a given attribute - * + * * @param {string} attributeName attribute name * @returns {Object?} stored attribute value */ - getAttribute(attributeName: string): Object { + getAttribute(attributeName: string): AttributeType { return this.attributesCache[attributeName]; } /** * Create or update all the given attributes - * + * * @param {[string, Object]} attributes attributes to create or update * @returns {boolean} attributes were stored */ @@ -40,16 +41,16 @@ export class AttributesCacheInMemory { /** * Retrieve the full attributes map - * - * @returns {Map} stored attributes + * + * @returns {Map} stored attributes */ - getAll(): Record { + getAll(): Record { return this.attributesCache; } /** * Removes a given attribute from the map - * + * * @param {string} attributeName attribute to remove * @returns {boolean} attribute removed */ @@ -63,7 +64,7 @@ export class AttributesCacheInMemory { /** * Clears all attributes stored in the SDK - * + * */ clear() { this.attributesCache = {}; diff --git a/src/storages/inMemory/EventsCacheInMemory.ts b/src/storages/inMemory/EventsCacheInMemory.ts index 64525cdf..5be2783b 100644 --- a/src/storages/inMemory/EventsCacheInMemory.ts +++ b/src/storages/inMemory/EventsCacheInMemory.ts @@ -1,4 +1,4 @@ -import { SplitIO } from '../../types'; +import { EventData } from '../../types'; import { IEventsCacheSync } from '../types'; const MAX_QUEUE_BYTE_SIZE = 5 * 1024 * 1024; // 5M @@ -7,7 +7,7 @@ export class EventsCacheInMemory implements IEventsCacheSync { private onFullQueue?: () => void; private readonly maxQueue: number; - private queue: SplitIO.EventData[]; + private queue: EventData[]; private queueByteSize: number; /** @@ -28,7 +28,7 @@ export class EventsCacheInMemory implements IEventsCacheSync { /** * Add a new event object at the end of the queue. */ - track(data: SplitIO.EventData, size = 0) { + track(data: EventData, size = 0) { this.queueByteSize += size; this.queue.push(data); @@ -48,7 +48,7 @@ export class EventsCacheInMemory implements IEventsCacheSync { /** * Pop the collected data, used as payload for posting. */ - pop(toMerge?: SplitIO.EventData[]) { + pop(toMerge?: EventData[]) { const data = this.queue; this.clear(); return toMerge ? toMerge.concat(data) : data; diff --git a/src/storages/inRedis/EventsCacheInRedis.ts b/src/storages/inRedis/EventsCacheInRedis.ts index e2702ab8..a486db2d 100644 --- a/src/storages/inRedis/EventsCacheInRedis.ts +++ b/src/storages/inRedis/EventsCacheInRedis.ts @@ -1,8 +1,8 @@ import { IEventsCacheAsync } from '../types'; import { IMetadata } from '../../dtos/types'; import { Redis } from 'ioredis'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { EventData } from '../../types'; +import { ILogger } from '../../types'; import { LOG_PREFIX } from './constants'; import { StoredEventWithMetadata } from '../../sync/submitters/types'; @@ -24,7 +24,7 @@ export class EventsCacheInRedis implements IEventsCacheAsync { * Add a new event object into the queue. * Unlike `impressions::track`, result promise is never rejected. */ - track(eventData: SplitIO.EventData): Promise { + track(eventData: EventData): Promise { return this.redis.rpush( this.key, this._toJSON(eventData) @@ -40,7 +40,7 @@ export class EventsCacheInRedis implements IEventsCacheAsync { /** * Generates the JSON as we'll store it on Redis. */ - private _toJSON(eventData: SplitIO.EventData): string { + private _toJSON(eventData: EventData): string { return JSON.stringify({ m: this.metadata, e: eventData diff --git a/src/storages/inRedis/ImpressionsCacheInRedis.ts b/src/storages/inRedis/ImpressionsCacheInRedis.ts index d4bd2d96..25bb7529 100644 --- a/src/storages/inRedis/ImpressionsCacheInRedis.ts +++ b/src/storages/inRedis/ImpressionsCacheInRedis.ts @@ -3,7 +3,7 @@ import { IMetadata } from '../../dtos/types'; import { ImpressionDTO } from '../../types'; import { Redis } from 'ioredis'; import { StoredImpressionWithMetadata } from '../../sync/submitters/types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; const IMPRESSIONS_TTL_REFRESH = 3600; // 1 hr diff --git a/src/storages/inRedis/RedisAdapter.ts b/src/storages/inRedis/RedisAdapter.ts index 45ef7b15..9bdb4d76 100644 --- a/src/storages/inRedis/RedisAdapter.ts +++ b/src/storages/inRedis/RedisAdapter.ts @@ -1,5 +1,5 @@ import ioredis from 'ioredis'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { merge, isString } from '../../utils/lang'; import { _Set, setToArray, ISet } from '../../utils/lang/sets'; import { thenable } from '../../utils/promise/thenable'; diff --git a/src/storages/inRedis/SegmentsCacheInRedis.ts b/src/storages/inRedis/SegmentsCacheInRedis.ts index a144e2b7..0efa364d 100644 --- a/src/storages/inRedis/SegmentsCacheInRedis.ts +++ b/src/storages/inRedis/SegmentsCacheInRedis.ts @@ -1,5 +1,5 @@ import { Redis } from 'ioredis'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { isNaNNumber } from '../../utils/lang'; import { LOG_PREFIX } from '../inLocalStorage/constants'; import { KeyBuilderSS } from '../KeyBuilderSS'; diff --git a/src/storages/inRedis/SplitsCacheInRedis.ts b/src/storages/inRedis/SplitsCacheInRedis.ts index 28996d06..55038453 100644 --- a/src/storages/inRedis/SplitsCacheInRedis.ts +++ b/src/storages/inRedis/SplitsCacheInRedis.ts @@ -1,7 +1,7 @@ import { isFiniteNumber, isNaNNumber } from '../../utils/lang'; import { KeyBuilderSS } from '../KeyBuilderSS'; import { Redis } from 'ioredis'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { LOG_PREFIX } from './constants'; import { ISplit } from '../../dtos/types'; import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync'; diff --git a/src/storages/inRedis/TelemetryCacheInRedis.ts b/src/storages/inRedis/TelemetryCacheInRedis.ts index 7f5ccd51..9fe9def2 100644 --- a/src/storages/inRedis/TelemetryCacheInRedis.ts +++ b/src/storages/inRedis/TelemetryCacheInRedis.ts @@ -1,4 +1,4 @@ -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { Method } from '../../sync/submitters/types'; import { KeyBuilderSS } from '../KeyBuilderSS'; import { ITelemetryCacheAsync } from '../types'; diff --git a/src/storages/inRedis/index.ts b/src/storages/inRedis/index.ts index b6022695..1cf53751 100644 --- a/src/storages/inRedis/index.ts +++ b/src/storages/inRedis/index.ts @@ -1,5 +1,6 @@ import { RedisAdapter } from './RedisAdapter'; -import { IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams } from '../types'; +import { IStorageAsync, IStorageFactoryParams } from '../types'; +import { StorageAsyncFactory } from '../../types'; import { validatePrefix } from '../KeyBuilder'; import { KeyBuilderSS } from '../KeyBuilderSS'; import { SplitsCacheInRedis } from './SplitsCacheInRedis'; @@ -18,7 +19,7 @@ export interface InRedisStorageOptions { * InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node. * @see {@link https://www.npmjs.com/package/ioredis} */ -export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsyncFactory { +export function InRedisStorage(options: InRedisStorageOptions = {}): StorageAsyncFactory { const prefix = validatePrefix(options.prefix); diff --git a/src/storages/pluggable/EventsCachePluggable.ts b/src/storages/pluggable/EventsCachePluggable.ts index d30d43b7..64fce20a 100644 --- a/src/storages/pluggable/EventsCachePluggable.ts +++ b/src/storages/pluggable/EventsCachePluggable.ts @@ -1,7 +1,7 @@ import { IPluggableStorageWrapper, IEventsCacheAsync } from '../types'; import { IMetadata } from '../../dtos/types'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { EventData } from '../../types'; +import { ILogger } from '../../types'; import { LOG_PREFIX } from './constants'; import { StoredEventWithMetadata } from '../../sync/submitters/types'; @@ -25,7 +25,7 @@ export class EventsCachePluggable implements IEventsCacheAsync { * @returns A promise that is resolved with a boolean value indicating if the push operation succeeded or failed. * Unlike `impressions::track`, The promise will never be rejected. */ - track(eventData: SplitIO.EventData): Promise { + track(eventData: EventData): Promise { return this.wrapper.pushItems( this.key, [this._toJSON(eventData)] @@ -38,7 +38,7 @@ export class EventsCachePluggable implements IEventsCacheAsync { }); } - private _toJSON(eventData: SplitIO.EventData): string { + private _toJSON(eventData: EventData): string { return JSON.stringify({ m: this.metadata, e: eventData diff --git a/src/storages/pluggable/ImpressionsCachePluggable.ts b/src/storages/pluggable/ImpressionsCachePluggable.ts index 4de3e33e..9fcbb43f 100644 --- a/src/storages/pluggable/ImpressionsCachePluggable.ts +++ b/src/storages/pluggable/ImpressionsCachePluggable.ts @@ -1,7 +1,7 @@ import { IPluggableStorageWrapper, IImpressionsCacheAsync } from '../types'; import { IMetadata } from '../../dtos/types'; import { ImpressionDTO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { StoredImpressionWithMetadata } from '../../sync/submitters/types'; export class ImpressionsCachePluggable implements IImpressionsCacheAsync { diff --git a/src/storages/pluggable/SegmentsCachePluggable.ts b/src/storages/pluggable/SegmentsCachePluggable.ts index 995c66df..128fa0d3 100644 --- a/src/storages/pluggable/SegmentsCachePluggable.ts +++ b/src/storages/pluggable/SegmentsCachePluggable.ts @@ -3,7 +3,7 @@ import { isNaNNumber } from '../../utils/lang'; import { KeyBuilderSS } from '../KeyBuilderSS'; import { IPluggableStorageWrapper, ISegmentsCacheAsync } from '../types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { LOG_PREFIX } from './constants'; import { _Set } from '../../utils/lang/sets'; diff --git a/src/storages/pluggable/SplitsCachePluggable.ts b/src/storages/pluggable/SplitsCachePluggable.ts index 6fec1420..f6baa794 100644 --- a/src/storages/pluggable/SplitsCachePluggable.ts +++ b/src/storages/pluggable/SplitsCachePluggable.ts @@ -1,7 +1,7 @@ import { isFiniteNumber, isNaNNumber } from '../../utils/lang'; import { KeyBuilder } from '../KeyBuilder'; import { IPluggableStorageWrapper } from '../types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { ISplit } from '../../dtos/types'; import { LOG_PREFIX } from './constants'; import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync'; diff --git a/src/storages/pluggable/TelemetryCachePluggable.ts b/src/storages/pluggable/TelemetryCachePluggable.ts index 24d344f5..2d208618 100644 --- a/src/storages/pluggable/TelemetryCachePluggable.ts +++ b/src/storages/pluggable/TelemetryCachePluggable.ts @@ -1,4 +1,4 @@ -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { Method } from '../../sync/submitters/types'; import { KeyBuilderSS } from '../KeyBuilderSS'; import { IPluggableStorageWrapper, ITelemetryCacheAsync } from '../types'; diff --git a/src/storages/pluggable/index.ts b/src/storages/pluggable/index.ts index c0ca4cc3..8d184dd0 100644 --- a/src/storages/pluggable/index.ts +++ b/src/storages/pluggable/index.ts @@ -1,5 +1,5 @@ -import { IPluggableStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams } from '../types'; - +import { IPluggableStorageWrapper, IStorageAsync, IStorageFactoryParams } from '../types'; +import { StorageAsyncFactory } from '../../types'; import { KeyBuilderSS } from '../KeyBuilderSS'; import { SplitsCachePluggable } from './SplitsCachePluggable'; import { SegmentsCachePluggable } from './SegmentsCachePluggable'; @@ -58,7 +58,7 @@ function promisifyEventsTrack(events: any) { /** * Pluggable storage factory for consumer server-side & client-side SplitFactory. */ -export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyncFactory { +export function PluggableStorage(options: PluggableStorageOptions): StorageAsyncFactory { validatePluggableStorageOptions(options); diff --git a/src/storages/pluggable/wrapperAdapter.ts b/src/storages/pluggable/wrapperAdapter.ts index c47a5d8b..83d38dad 100644 --- a/src/storages/pluggable/wrapperAdapter.ts +++ b/src/storages/pluggable/wrapperAdapter.ts @@ -1,4 +1,4 @@ -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { IPluggableStorageWrapper } from '../types'; import { LOG_PREFIX } from './constants'; diff --git a/src/storages/types.ts b/src/storages/types.ts index 1029ad62..d2894042 100644 --- a/src/storages/types.ts +++ b/src/storages/types.ts @@ -1,7 +1,6 @@ -import { MaybeThenable, IMetadata, ISplitFiltersValidation } from '../dtos/types'; -import { ILogger } from '../logger/types'; +import { MaybeThenable, IMetadata } from '../dtos/types'; import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent } from '../sync/submitters/types'; -import { SplitIO, ImpressionDTO, SDKMode } from '../types'; +import { ImpressionDTO, SDKMode, ILogger, EventData, ISplitFiltersValidation } from '../types'; /** * Interface of a pluggable storage wrapper. @@ -289,7 +288,7 @@ export interface IImpressionsCacheBase { export interface IEventsCacheBase { // Consumer API method, used by events tracker, in standalone and consumer modes, to push events into the storage. - track(data: SplitIO.EventData, size?: number): MaybeThenable + track(data: EventData, size?: number): MaybeThenable } /** Impressions and events cache for standalone mode (sync) */ @@ -312,8 +311,8 @@ export interface IImpressionsCacheSync extends IImpressionsCacheBase, IRecorderC setOnFullQueueCb(cb: () => void): void } -export interface IEventsCacheSync extends IEventsCacheBase, IRecorderCacheProducerSync { - track(data: SplitIO.EventData, size?: number): boolean +export interface IEventsCacheSync extends IEventsCacheBase, IRecorderCacheProducerSync { + track(data: EventData, size?: number): boolean /* Registers callback for full queue */ setOnFullQueueCb(cb: () => void): void } @@ -339,7 +338,7 @@ export interface IImpressionsCacheAsync extends IImpressionsCacheBase, IRecorder export interface IEventsCacheAsync extends IEventsCacheBase, IRecorderCacheProducerAsync { // Consumer API method, used by events tracker (in standalone and consumer modes) to push data into. // The result promise cannot reject. - track(data: SplitIO.EventData, size?: number): Promise + track(data: EventData, size?: number): Promise } /** @@ -352,7 +351,7 @@ export interface IImpressionCountsCacheSync extends IRecorderCacheProducerSync ): Record // pop cache data + pop(toMerge?: Record): Record // pop cache data } @@ -495,14 +494,39 @@ export interface IStorageFactoryParams { metadata: IMetadata, } -export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE'; - -export type IStorageSyncFactory = { - readonly type: StorageType, - (params: IStorageFactoryParams): IStorageSync -} - -export type IStorageAsyncFactory = { - type: StorageType, - (params: IStorageFactoryParams): IStorageAsync +/** + * Defines the format of Split data to preload on the factory storage (cache). + */ +export interface PreloadedData { + /** + * Timestamp of the last moment the data was synchronized with Split servers. + * If this value is older than 10 days ago (expiration time policy), the data is not used to update the storage content. + * @TODO configurable expiration time policy? + */ + lastUpdated: number, + /** + * Change number of the preloaded data. + * If this value is older than the current changeNumber at the storage, the data is not used to update the storage content. + */ + since: number, + /** + * Map of splits to their serialized definitions. + */ + splitsData: { + [splitName: string]: string + }, + /** + * Optional map of user keys to their list of segments. + * @TODO remove when releasing first version + */ + mySegmentsData?: { + [key: string]: string[] + }, + /** + * Optional map of segments to their serialized definitions. + * This property is ignored if `mySegmentsData` was provided. + */ + segmentsData?: { + [segmentName: string]: string + }, } diff --git a/src/sync/offline/LocalhostFromObject.ts b/src/sync/offline/LocalhostFromObject.ts index b823e7ee..d90d3003 100644 --- a/src/sync/offline/LocalhostFromObject.ts +++ b/src/sync/offline/LocalhostFromObject.ts @@ -1,12 +1,12 @@ import { splitsParserFromSettingsFactory } from './splitsParser/splitsParserFromSettings'; import { syncManagerOfflineFactory } from './syncManagerOffline'; -import { SplitIO } from '../../types'; +import { LocalhostFactory } from '../../types'; // Singleton instance of the factory function for offline SyncManager from object (a.k.a. localhostFromObject) // SDK instances instantiate their SyncManagers with the same factory -const localhostFromObject = syncManagerOfflineFactory(splitsParserFromSettingsFactory) as SplitIO.LocalhostFactory; +const localhostFromObject: any = syncManagerOfflineFactory(splitsParserFromSettingsFactory); localhostFromObject.type = 'LocalhostFromObject'; -export function LocalhostFromObject(): SplitIO.LocalhostFactory { - return localhostFromObject; +export function LocalhostFromObject() { + return localhostFromObject as LocalhostFactory; } diff --git a/src/sync/offline/splitsParser/splitsParserFromSettings.ts b/src/sync/offline/splitsParser/splitsParserFromSettings.ts index 8e892969..3eb8f5df 100644 --- a/src/sync/offline/splitsParser/splitsParserFromSettings.ts +++ b/src/sync/offline/splitsParser/splitsParserFromSettings.ts @@ -1,23 +1,23 @@ import { ISplitPartial } from '../../../dtos/types'; -import { ISettings, SplitIO } from '../../../types'; +import { ISettings, MockedFeaturesMap, TreatmentWithConfig } from '../../../types'; import { isObject, forOwn } from '../../../utils/lang'; import { parseCondition } from './parseCondition'; -function hasTreatmentChanged(prev: string | SplitIO.TreatmentWithConfig, curr: string | SplitIO.TreatmentWithConfig) { +function hasTreatmentChanged(prev: string | TreatmentWithConfig, curr: string | TreatmentWithConfig) { if (typeof prev !== typeof curr) return true; if (typeof prev === 'string') { // strings treatments, just compare return prev !== curr; } else { // has treatment and config, compare both - return prev.treatment !== (curr as SplitIO.TreatmentWithConfig).treatment || prev.config !== (curr as SplitIO.TreatmentWithConfig).config; + return prev.treatment !== (curr as TreatmentWithConfig).treatment || prev.config !== (curr as TreatmentWithConfig).config; } } export function splitsParserFromSettingsFactory() { - let previousMock: SplitIO.MockedFeaturesMap = { 'emptyMock': '1' }; + let previousMock: MockedFeaturesMap = { 'emptyMock': '1' }; - function mockUpdated(currentData: SplitIO.MockedFeaturesMap) { + function mockUpdated(currentData: MockedFeaturesMap) { const names = Object.keys(currentData); // Different amount of items @@ -42,7 +42,7 @@ export function splitsParserFromSettingsFactory() { * @param settings validated object with mocked features mapping. */ return function splitsParserFromSettings(settings: ISettings): false | Record { - const features = settings.features as SplitIO.MockedFeaturesMap || {}; + const features = settings.features as MockedFeaturesMap || {}; if (!mockUpdated(features)) return false; @@ -53,8 +53,8 @@ export function splitsParserFromSettingsFactory() { let config = null; if (isObject(data)) { - treatment = (data as SplitIO.TreatmentWithConfig).treatment; - config = (data as SplitIO.TreatmentWithConfig).config || config; + treatment = (data as TreatmentWithConfig).treatment; + config = (data as TreatmentWithConfig).config || config; } const configurations: Record = {}; if (config !== null) configurations[treatment as string] = config; diff --git a/src/sync/polling/updaters/mySegmentsUpdater.ts b/src/sync/polling/updaters/mySegmentsUpdater.ts index 421e0c3f..34ca939d 100644 --- a/src/sync/polling/updaters/mySegmentsUpdater.ts +++ b/src/sync/polling/updaters/mySegmentsUpdater.ts @@ -3,7 +3,7 @@ import { ISegmentsCacheSync, ISplitsCacheSync } from '../../../storages/types'; import { ISegmentsEventEmitter } from '../../../readiness/types'; import { timeout } from '../../../utils/promise/timeout'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants'; import { MySegmentsData } from '../types'; diff --git a/src/sync/polling/updaters/segmentChangesUpdater.ts b/src/sync/polling/updaters/segmentChangesUpdater.ts index f9f04dcb..63240cc3 100644 --- a/src/sync/polling/updaters/segmentChangesUpdater.ts +++ b/src/sync/polling/updaters/segmentChangesUpdater.ts @@ -4,7 +4,7 @@ import { IReadinessManager } from '../../../readiness/types'; import { MaybeThenable } from '../../../dtos/types'; import { findIndex } from '../../../utils/lang'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC_SEGMENTS } from '../../../logger/constants'; import { thenable } from '../../../utils/promise/thenable'; diff --git a/src/sync/polling/updaters/splitChangesUpdater.ts b/src/sync/polling/updaters/splitChangesUpdater.ts index ffea8cd6..060d0776 100644 --- a/src/sync/polling/updaters/splitChangesUpdater.ts +++ b/src/sync/polling/updaters/splitChangesUpdater.ts @@ -5,7 +5,7 @@ import { ISplit, ISplitChangesResponse } from '../../../dtos/types'; import { ISplitsEventEmitter } from '../../../readiness/types'; import { timeout } from '../../../utils/promise/timeout'; import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants'; -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; import { SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants'; type ISplitChangesUpdater = (noCache?: boolean, till?: number) => Promise diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index d8f20b32..d29f250f 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -4,7 +4,7 @@ import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, MY_S import { IPushEventEmitter } from '../types'; import { ISseEventHandler } from '../SSEClient/types'; import { INotificationError, INotificationMessage } from './types'; -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; import { STREAMING_PARSING_ERROR_FAILS, ERROR_STREAMING_SSE, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_NEW_MESSAGE } from '../../../logger/constants'; import { ABLY_ERROR, NON_REQUESTED, SSE_CONNECTION_ERROR } from '../../../utils/constants'; import { ITelemetryTracker } from '../../../trackers/types'; diff --git a/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts b/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts index 93454f0e..006975d4 100644 --- a/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +++ b/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts @@ -1,4 +1,4 @@ -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; import { ISegmentsCacheSync } from '../../../storages/types'; import { Backoff } from '../../../utils/Backoff'; import { ISegmentsSyncTask } from '../../polling/types'; diff --git a/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts b/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts index 1a1264df..d768f4e4 100644 --- a/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +++ b/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts @@ -1,4 +1,4 @@ -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants'; import { ISplitsEventEmitter } from '../../../readiness/types'; import { ISplitsCacheSync } from '../../../storages/types'; diff --git a/src/sync/submitters/submitter.ts b/src/sync/submitters/submitter.ts index 2cf16d7c..878c56e2 100644 --- a/src/sync/submitters/submitter.ts +++ b/src/sync/submitters/submitter.ts @@ -1,7 +1,7 @@ import { syncTaskFactory } from '../syncTask'; import { ISyncTask } from '../types'; import { IRecorderCacheProducerSync } from '../../storages/types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { SUBMITTERS_PUSH, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY } from '../../logger/constants'; import { IResponse } from '../../services/types'; diff --git a/src/sync/submitters/types.ts b/src/sync/submitters/types.ts index fe9fac26..b42d014d 100644 --- a/src/sync/submitters/types.ts +++ b/src/sync/submitters/types.ts @@ -1,5 +1,5 @@ import { IMetadata } from '../../dtos/types'; -import { SplitIO } from '../../types'; +import { EventData } from '../../types'; import { ISyncTask } from '../types'; export type ImpressionsPayload = { @@ -61,7 +61,7 @@ export type StoredEventWithMetadata = { /** Metadata */ m: IMetadata, /** Stored event */ - e: SplitIO.EventData + e: EventData } /** diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index 035a9c59..07068fa4 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -1,5 +1,5 @@ import { SYNC_TASK_EXECUTE, SYNC_TASK_START, SYNC_TASK_STOP } from '../logger/constants'; -import { ILogger } from '../logger/types'; +import { ILogger } from '../types'; import { ISyncTask } from './types'; /** diff --git a/src/trackers/__tests__/eventTracker.spec.ts b/src/trackers/__tests__/eventTracker.spec.ts index 18dba632..38285964 100644 --- a/src/trackers/__tests__/eventTracker.spec.ts +++ b/src/trackers/__tests__/eventTracker.spec.ts @@ -1,4 +1,4 @@ -import { SplitIO } from '../../types'; +import { EventData } from '../../types'; import { QUEUED } from '../../utils/constants'; import { fullSettings } from '../../utils/settingsValidation/__tests__/settings.mocks'; import { eventTrackerFactory } from '../eventTracker'; @@ -41,7 +41,7 @@ describe('Event Tracker', () => { }); test('Propagate the event into the event cache and integrations manager, and return its result (a boolean or a promise that resolves to boolean)', async () => { - fakeEventsCache.track.mockImplementation((eventData: SplitIO.EventData, size: number) => { + fakeEventsCache.track.mockImplementation((eventData: EventData, size: number) => { if (eventData === fakeEvent) { switch (size) { case 1: return true; diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 878800d3..ac3f090b 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -2,7 +2,7 @@ import { objectAssign } from '../utils/lang/objectAssign'; import { thenable } from '../utils/promise/thenable'; import { IEventsCacheBase, ITelemetryCacheAsync, ITelemetryCacheSync } from '../storages/types'; import { IEventsHandler, IEventTracker } from './types'; -import { ISettings, SplitIO } from '../types'; +import { ISettings, EventData } from '../types'; import { EVENTS_TRACKER_SUCCESS, ERROR_EVENTS_TRACKER } from '../logger/constants'; import { CONSENT_DECLINED, DROPPED, QUEUED } from '../utils/constants'; import { isStorageSync } from './impressionObserver/utils'; @@ -23,7 +23,7 @@ export function eventTrackerFactory( const log = settings.log; const isSync = isStorageSync(settings); - function queueEventsCallback(eventData: SplitIO.EventData, tracked: boolean) { + function queueEventsCallback(eventData: EventData, tracked: boolean) { const { eventTypeId, trafficTypeName, key, value, timestamp, properties } = eventData; // Logging every prop would be too much. const msg = `event of type "${eventTypeId}" for traffic type "${trafficTypeName}". Key: ${key}. Value: ${value}. Timestamp: ${timestamp}. ${properties ? 'With properties.' : 'With no properties.'}`; @@ -48,7 +48,7 @@ export function eventTrackerFactory( } return { - track(eventData: SplitIO.EventData, size?: number) { + track(eventData: EventData, size?: number) { if (settings.userConsent === CONSENT_DECLINED) { return isSync ? false : Promise.resolve(false); } diff --git a/src/trackers/impressionObserver/__tests__/testUtils.ts b/src/trackers/impressionObserver/__tests__/testUtils.ts index a41b9f24..43febf4f 100644 --- a/src/trackers/impressionObserver/__tests__/testUtils.ts +++ b/src/trackers/impressionObserver/__tests__/testUtils.ts @@ -1,7 +1,7 @@ import { ImpressionDTO } from '../../../types'; -export function generateImpressions(count: number): ImpressionDTO[] { - const impressions = []; +export function generateImpressions(count: number) { + const impressions: ImpressionDTO[] = []; for (let i = 0; i < count; i++) { impressions.push({ keyName: `key_${i}`, diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index 61b8e2cb..36389c44 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -3,7 +3,7 @@ import { thenable } from '../utils/promise/thenable'; import { truncateTimeFrame } from '../utils/time'; import { IImpressionCountsCacheSync, IImpressionsCacheBase, ITelemetryCacheSync, ITelemetryCacheAsync } from '../storages/types'; import { IImpressionsHandler, IImpressionsTracker } from './types'; -import { SplitIO, ImpressionDTO, ISettings } from '../types'; +import { ImpressionDTO, ISettings, Attributes, ImpressionData } from '../types'; import { IImpressionObserver } from './impressionObserver/types'; import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER } from '../logger/constants'; import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants'; @@ -32,7 +32,7 @@ export function impressionsTrackerFactory( const { log, impressionListener, runtime: { ip, hostname }, version } = settings; return { - track(impressions: ImpressionDTO[], attributes?: SplitIO.Attributes) { + track(impressions: ImpressionDTO[], attributes?: Attributes) { if (settings.userConsent === CONSENT_DECLINED) return; const impressionsCount = impressions.length; @@ -78,7 +78,7 @@ export function impressionsTrackerFactory( // @TODO next block might be handled by the integration manager. In that case, the metadata object doesn't need to be passed in the constructor if (impressionListener || integrationsManager) { for (let i = 0; i < impressionsCount; i++) { - const impressionData: SplitIO.ImpressionData = { + const impressionData: ImpressionData = { // copy of impression, to avoid unexpected behaviour if modified by integrations or impressionListener impression: objectAssign({}, impressions[i]), attributes, diff --git a/src/trackers/types.ts b/src/trackers/types.ts index 2ba70832..176e66b2 100644 --- a/src/trackers/types.ts +++ b/src/trackers/types.ts @@ -1,4 +1,4 @@ -import { SplitIO, ImpressionDTO } from '../types'; +import { ImpressionDTO, EventData, ImpressionData, Attributes } from '../types'; import { StreamingEventType, Method, OperationType } from '../sync/submitters/types'; import { IEventsCacheBase } from '../storages/types'; import { NetworkError } from '../services/types'; @@ -6,7 +6,7 @@ import { NetworkError } from '../services/types'; /** Events tracker */ export interface IEventsHandler { - handleEvent(eventData: SplitIO.EventData): any + handleEvent(eventData: EventData): any } export type IEventTracker = IEventsCacheBase @@ -14,11 +14,11 @@ export type IEventTracker = IEventsCacheBase /** Impressions tracker */ export interface IImpressionsHandler { - handleImpression(impressionData: SplitIO.ImpressionData): any + handleImpression(impressionData: ImpressionData): any } export interface IImpressionsTracker { - track(impressions: ImpressionDTO[], attributes?: SplitIO.Attributes): void + track(impressions: ImpressionDTO[], attributes?: Attributes): void } /** Telemetry tracker */ diff --git a/src/splitio.d.ts b/src/types.d.ts similarity index 76% rename from src/splitio.d.ts rename to src/types.d.ts index 6e71a45a..4ed7e1ed 100644 --- a/src/splitio.d.ts +++ b/src/types.d.ts @@ -8,342 +8,340 @@ export as namespace SplitIO; export = SplitIO; +/****** Exposed namespace ******/ /** - * EventEmitter interface based on a subset of the NodeJS.EventEmitter methods. - */ -interface IEventEmitter { - addListener(event: string, listener: (...args: any[]) => void): this - on(event: string, listener: (...args: any[]) => void): this - once(event: string, listener: (...args: any[]) => void): this - removeListener(event: string, listener: (...args: any[]) => void): this - off(event: string, listener: (...args: any[]) => void): this - removeAllListeners(event?: string): this - emit(event: string, ...args: any[]): boolean -} -/** - * @typedef {Object} EventConsts - * @property {string} SDK_READY The ready event. - * @property {string} SDK_READY_FROM_CACHE The ready event when fired with cached data. - * @property {string} SDK_READY_TIMED_OUT The timeout event. - * @property {string} SDK_UPDATE The update event. - */ -type EventConsts = { - SDK_READY: 'init::ready', - SDK_READY_FROM_CACHE: 'init::cache-ready', - SDK_READY_TIMED_OUT: 'init::timeout', - SDK_UPDATE: 'state::update' -}; -/** - * SDK Modes. - * @typedef {string} SDKMode - */ -type SDKMode = 'standalone' | 'localhost' | 'consumer' | 'consumer_partial'; -/** - * Storage types. - * @typedef {string} StorageType - */ -type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS'; -// @TODO? specialize ISettings for ISDK, IBrowserSDK, etc? -/** - * Settings interface. This is a representation of the settings the SDK expose, that's why - * most of it's props are readonly. Only features should be rewritten when localhost mode is active. - * @interface ISettings - */ -interface ISettings { - readonly core: { - authorizationKey: string, - key?: SplitIO.SplitKey, - trafficType?: string, - labelsEnabled: boolean, - IPAddressesEnabled?: boolean - }, - readonly mode: SDKMode, - readonly scheduler: { - featuresRefreshRate: number, - impressionsRefreshRate: number, - impressionsQueueSize: number, - /** - * @deprecated - */ - metricsRefreshRate?: number, - telemetryRefreshRate: number, - segmentsRefreshRate: number, - offlineRefreshRate: number, - eventsPushRate: number, - eventsQueueSize: number, - pushRetryBackoffBase: number - }, - readonly startup: { - readyTimeout: number, - requestTimeoutBeforeReady: number, - retriesOnFailureBeforeReady: number, - eventsFirstPushWindow: number - }, - readonly storage: { - prefix: string, - options: Object, - type: StorageType - } | SplitIO.StorageSyncFactory | SplitIO.StorageAsyncFactory, - readonly urls: { - events: string, - sdk: string, - auth: string, - streaming: string, - telemetry: string - }, - readonly integrations?: SplitIO.BrowserIntegration[] | SplitIO.IntegrationFactory[], - readonly debug: boolean | LogLevel | SplitIO.ILogger, - readonly version: string, - /** - * Mocked features map. - */ - features?: SplitIO.MockedFeaturesMap | SplitIO.MockedFeaturesFilePath, - readonly streamingEnabled: boolean, - readonly sync: { - splitFilters: SplitIO.SplitFilter[], - impressionsMode: SplitIO.ImpressionsMode, - enabled: boolean, - localhostMode?: SplitIO.LocalhostFactory - }, - /** - * User consent status if using in browser. Undefined if using in NodeJS. - */ - readonly userConsent?: SplitIO.ConsentStatus -} -/** - * Log levels. - * @typedef {string} LogLevel - */ -type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE'; -/** - * Logger API - * @interface ILoggerAPI + * Types and interfaces for @splitsoftware/splitio package for usage when integrating javascript sdk on typescript apps. + * For the SDK package information + * @see {@link https://www.npmjs.com/package/@splitsoftware/splitio} */ -interface ILoggerAPI { +declare namespace SplitIO { /** - * Enables SDK logging to the console. - * @function enable - * @returns {void} + * Reduced version of NodeJS.EventEmitter interface with the minimal methods used by the SDK + * @see {@link https://nodejs.org/api/events.html} */ - enable(): void, + interface IEventEmitter { + addListener(event: string, listener: (...args: any[]) => void): this + on(event: string, listener: (...args: any[]) => void): this + once(event: string, listener: (...args: any[]) => void): this + removeListener(event: string, listener: (...args: any[]) => void): this + off(event: string, listener: (...args: any[]) => void): this + removeAllListeners(event?: string): this + emit(event: string, ...args: any[]): boolean + } /** - * Disables SDK logging. - * @function disable - * @returns {void} + * impression DTO generated by the Sdk client when processing evaluations */ - disable(): void, + type ImpressionDTO = { + feature: string, + keyName: string, + treatment: string, + time: number, + bucketingKey?: string, + label: string, + changeNumber: number, + pt?: number, + } /** - * Sets a log level for the SDK logs. - * @function setLogLevel - * @returns {void} - */ - setLogLevel(logLevel: LogLevel): void, + * @typedef {Object} EventConsts + * @property {string} SDK_READY The ready event. + * @property {string} SDK_READY_FROM_CACHE The ready event when fired with cached data. + * @property {string} SDK_READY_TIMED_OUT The timeout event. + * @property {string} SDK_UPDATE The update event. + */ + type EventConsts = { + SDK_READY: 'init::ready', + SDK_READY_FROM_CACHE: 'init::cache-ready', + SDK_READY_TIMED_OUT: 'init::timeout', + SDK_UPDATE: 'state::update' + }; /** - * Log level constants. Use this to pass them to setLogLevel function. + * SDK Modes. + * @typedef {string} SDKMode */ - LogLevel: { - [level in LogLevel]: LogLevel - } -} -/** - * User consent API - * @interface IUserConsentAPI - */ -interface IUserConsentAPI { + type SDKMode = 'standalone' | 'localhost' | 'consumer' | 'consumer_partial'; /** - * Set or update the user consent status. Possible values are `true` and `false`, which represent user consent `'GRANTED'` and `'DECLINED'` respectively. - * - `true ('GRANTED')`: the user has granted consent for tracking events and impressions. The SDK will send them to Split cloud. - * - `false ('DECLINED')`: the user has declined consent for tracking events and impressions. The SDK will not send them to Split cloud. - * - * NOTE: calling this method updates the user consent at a factory level, affecting all clients of the same factory. - * - * @function setStatus - * @param {boolean} userConsent The user consent status, true for 'GRANTED' and false for 'DECLINED'. - * @returns {boolean} Whether the provided param is a valid value (i.e., a boolean value) or not. + * Storage types. + * @typedef {string} StorageType */ - setStatus(userConsent: boolean): boolean; + type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE'; /** - * Get the user consent status. - * - * @function getStatus - * @returns {ConsentStatus} The user consent status. + * Settings interface. This is a representation of the settings the SDK expose, that's why + * most of it's props are readonly. Only features should be rewritten when localhost mode is active. + * @interface ISettings */ - getStatus(): SplitIO.ConsentStatus; + interface ISettings { + readonly core: { + authorizationKey: string, + key?: SplitKey, + trafficType?: string, + labelsEnabled: boolean, + IPAddressesEnabled?: boolean + }, + readonly mode: SDKMode, + readonly scheduler: { + featuresRefreshRate: number, + impressionsRefreshRate: number, + impressionsQueueSize: number, + /** + * @deprecated + */ + metricsRefreshRate?: number, + telemetryRefreshRate: number, + segmentsRefreshRate: number, + offlineRefreshRate: number, + eventsPushRate: number, + eventsQueueSize: number, + pushRetryBackoffBase: number + }, + readonly startup: { + readyTimeout: number, + requestTimeoutBeforeReady: number, + retriesOnFailureBeforeReady: number, + eventsFirstPushWindow: number + }, + readonly storage: { + prefix: string, + options: Object, + type: StorageType + } | StorageSyncFactory | StorageAsyncFactory, + readonly urls: { + events: string, + sdk: string, + auth: string, + streaming: string, + telemetry: string + }, + readonly integrations?: BrowserIntegration[] | IntegrationFactory[], + readonly debug: boolean | LogLevel | ILogger, + readonly version: string, + /** + * Mocked features map. + */ + features?: MockedFeaturesMap | MockedFeaturesFilePath, + readonly streamingEnabled: boolean, + readonly sync: { + splitFilters: SplitFilter[], + impressionsMode: ImpressionsMode, + enabled: boolean, + localhostMode?: LocalhostFactory, + __splitFiltersValidation: ISplitFiltersValidation, + }, + readonly runtime: { + ip: string | false + hostname: string | false + }, + readonly log: ILogger + readonly impressionListener?: unknown + /** + * User consent status if using in browser. Undefined if using in NodeJS. + */ + readonly userConsent?: ConsentStatus + } /** - * Consent status constants. Use this to compare with the getStatus function result. + * Log levels. + * @typedef {string} LogLevel */ - Status: { - [status in SplitIO.ConsentStatus]: SplitIO.ConsentStatus - } -} -/** - * Common settings between Browser and NodeJS settings interface. - * @interface ISharedSettings - */ -interface ISharedSettings { + type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE'; /** - * SDK Core settings. - * @property {Object} core + * Logger API + * @interface ILoggerAPI */ - core: { + interface ILoggerAPI { /** - * Your API key. More information: @see {@link https://help.split.io/hc/en-us/articles/360019916211-API-keys} - * @property {string} authorizationKey + * Enables SDK logging to the console. + * @function enable + * @returns {void} */ - authorizationKey: string, + enable(): void, /** - * Disable labels from being sent to Split backend. Labels may contain sensitive information. - * This configuration is applicable if the SDK is running in "standalone" or "partial consumer" mode. - * @property {boolean} labelsEnabled - * @default true + * Disables SDK logging. + * @function disable + * @returns {void} */ - labelsEnabled?: boolean - }, - /** - * The SDK mode. Possible values are "standalone", which is the default when using a synchronous storage, like 'MEMORY' and 'LOCALSTORAGE', - * and "consumer", which must be set when using an asynchronous storage, like 'REDIS'. For "localhost" mode, use "localhost" as authorizationKey. - * @property {SDKMode} mode - * @default standalone - */ - mode?: SDKMode, - /** - * The impression listener, which is optional. Whatever you provide here needs to comply with the SplitIO.IImpressionListener interface, - * which will check for the logImpression method. - * @property {IImpressionListener} impressionListener - * @default undefined - */ - impressionListener?: SplitIO.IImpressionListener, - /** - * Boolean flag to enable the streaming service as default synchronization mechanism. In the event of any issue with streaming, - * the SDK would fallback to the polling mechanism. If false, the SDK would poll for changes as usual without attempting to use streaming. - * This configuration is applicable if the SDK is running in "standalone" mode. - * @property {boolean} streamingEnabled - * @default true - */ - streamingEnabled?: boolean, + disable(): void, + /** + * Sets a log level for the SDK logs. + * @function setLogLevel + * @returns {void} + */ + setLogLevel(logLevel: LogLevel): void, + /** + * Log level constants. Use this to pass them to setLogLevel function. + */ + LogLevel: { + [level in LogLevel]: LogLevel + } + } /** - * SDK synchronization settings. - * @property {Object} sync + * User consent API + * @interface IUserConsentAPI */ - sync?: { + interface IUserConsentAPI { /** - * List of Split filters. These filters are used to fetch a subset of the Splits definitions in your environment, in order to reduce the delay of the SDK to be ready. - * This configuration is applicable if the SDK is running in "standalone" mode. + * Set or update the user consent status. Possible values are `true` and `false`, which represent user consent `'GRANTED'` and `'DECLINED'` respectively. + * - `true ('GRANTED')`: the user has granted consent for tracking events and impressions. The SDK will send them to Split cloud. + * - `false ('DECLINED')`: the user has declined consent for tracking events and impressions. The SDK will not send them to Split cloud. * - * At the moment, two types of split filters are supported: by name and by prefix. + * NOTE: calling this method updates the user consent at a factory level, affecting all clients of the same factory. * - * Example: - * `splitFilter: [ - * { type: 'byName', values: ['my_split_1', 'my_split_2'] }, // will fetch splits named 'my_split_1' and 'my_split_2' - * { type: 'byPrefix', values: ['testing'] } // will fetch splits whose names start with 'testing__' prefix - * ]` - * @property {SplitIO.SplitFilter[]} splitFilters + * @function setStatus + * @param {boolean} userConsent The user consent status, true for 'GRANTED' and false for 'DECLINED'. + * @returns {boolean} Whether the provided param is a valid value (i.e., a boolean value) or not. */ - splitFilters?: SplitIO.SplitFilter[] + setStatus(userConsent: boolean): boolean; /** - * Impressions Collection Mode. Option to determine how impressions are going to be sent to Split Servers. - * Possible values are 'DEBUG' and 'OPTIMIZED'. - * - DEBUG: will send all the impressions generated (recommended only for debugging purposes). - * - OPTIMIZED: will send unique impressions to Split Servers avoiding a considerable amount of traffic that duplicated impressions could generate. - * @property {string} impressionsMode - * @default 'OPTIMIZED' + * Get the user consent status. + * + * @function getStatus + * @returns {ConsentStatus} The user consent status. */ - impressionsMode?: SplitIO.ImpressionsMode, + getStatus(): ConsentStatus; /** - * Controls the SDK continuous synchronization flags. - * - * When `true` a running SDK will process rollout plan updates performed on the UI (default). - * When false it'll just fetch all data upon init. - * This configuration is applicable if the SDK is running in "standalone" mode. - * - * @property {boolean} enabled - * @default true + * Consent status constants. Use this to compare with the getStatus function result. */ - enabled?: boolean - }, - /** - * List of URLs that the SDK will use as base for it's synchronization functionalities. - * This configuration is applicable if the SDK is running in "standalone" or "partial consumer" mode. - * Do not change these settings unless you're working an advanced use case, like connecting to the Split proxy. - * @property {Object} urls - */ - urls?: SplitIO.UrlSettings, -} -// @TODO Should extends IEventEmitter for React Native and JS Browser SDK -/** - * Common API for entities that expose status handlers. - * @interface IStatusInterface - * @extends IEventEmitter - */ -interface IStatusInterface extends IEventEmitter { - /** - * Constant object containing the SDK events for you to use. - * @property {EventConsts} Event - */ - Event: EventConsts, + Status: { + [status in ConsentStatus]: ConsentStatus + } + } /** - * Returns a promise that will be resolved once the SDK has finished loading (SDK_READY event emitted) or rejected if the SDK has timedout (SDK_READY_TIMED_OUT event emitted). - * As it's meant to provide similar flexibility to the event approach, given that the SDK might be eventually ready after a timeout event, calling the `ready` method after the - * SDK had timed out will return a new promise that should eventually resolve if the SDK gets ready. - * - * Caveats: the method was designed to avoid an unhandled Promise rejection if the rejection case is not handled, so that `onRejected` handler is optional when using promises. - * However, when using async/await syntax, the rejection should be explicitly propagated like in the following example: - * ``` - * try { - * await client.ready().catch((e) => { throw e; }); - * // SDK is ready - * } catch(e) { - * // SDK has timedout - * } - * ``` - * - * @function ready - * @returns {Promise} + * Common settings between Browser and NodeJS settings interface. + * @interface ISharedSettings */ - ready(): Promise -} -/** - * Common definitions between clients for different environments interface. - * @interface IBasicClient - * @extends IStatusInterface - */ -interface IBasicClient extends IStatusInterface { + interface ISharedSettings { + /** + * SDK Core settings. + * @property {Object} core + */ + core: { + /** + * Your API key. More information: @see {@link https://help.split.io/hc/en-us/articles/360019916211-API-keys} + * @property {string} authorizationKey + */ + authorizationKey: string, + /** + * Disable labels from being sent to Split backend. Labels may contain sensitive information. + * This configuration is applicable if the SDK is running in "standalone" or "partial consumer" mode. + * @property {boolean} labelsEnabled + * @default true + */ + labelsEnabled?: boolean + }, + /** + * The SDK mode. Possible values are "standalone", which is the default when using a synchronous storage, like 'MEMORY' and 'LOCALSTORAGE', + * and "consumer", which must be set when using an asynchronous storage, like 'REDIS'. For "localhost" mode, use "localhost" as authorizationKey. + * @property {SDKMode} mode + * @default standalone + */ + mode?: SDKMode, + /** + * The impression listener, which is optional. Whatever you provide here needs to comply with the IImpressionListener interface, + * which will check for the logImpression method. + * @property {IImpressionListener} impressionListener + * @default undefined + */ + impressionListener?: IImpressionListener, + /** + * Boolean flag to enable the streaming service as default synchronization mechanism. In the event of any issue with streaming, + * the SDK would fallback to the polling mechanism. If false, the SDK would poll for changes as usual without attempting to use streaming. + * This configuration is applicable if the SDK is running in "standalone" mode. + * @property {boolean} streamingEnabled + * @default true + */ + streamingEnabled?: boolean, + /** + * SDK synchronization settings. + * @property {Object} sync + */ + sync?: { + /** + * List of Split filters. These filters are used to fetch a subset of the Splits definitions in your environment, in order to reduce the delay of the SDK to be ready. + * This configuration is applicable if the SDK is running in "standalone" mode. + * + * At the moment, two types of split filters are supported: by name and by prefix. + * + * Example: + * `splitFilter: [ + * { type: 'byName', values: ['my_split_1', 'my_split_2'] }, // will fetch splits named 'my_split_1' and 'my_split_2' + * { type: 'byPrefix', values: ['testing'] } // will fetch splits whose names start with 'testing__' prefix + * ]` + * @property {SplitFilter[]} splitFilters + */ + splitFilters?: SplitFilter[] + /** + * Impressions Collection Mode. Option to determine how impressions are going to be sent to Split Servers. + * Possible values are 'DEBUG' and 'OPTIMIZED'. + * - DEBUG: will send all the impressions generated (recommended only for debugging purposes). + * - OPTIMIZED: will send unique impressions to Split Servers avoiding a considerable amount of traffic that duplicated impressions could generate. + * @property {string} impressionsMode + * @default 'OPTIMIZED' + */ + impressionsMode?: ImpressionsMode, + /** + * Controls the SDK continuous synchronization flags. + * + * When `true` a running SDK will process rollout plan updates performed on the UI (default). + * When false it'll just fetch all data upon init. + * This configuration is applicable if the SDK is running in "standalone" mode. + * + * @property {boolean} enabled + * @default true + */ + enabled?: boolean + }, + /** + * List of URLs that the SDK will use as base for it's synchronization functionalities. + * This configuration is applicable if the SDK is running in "standalone" or "partial consumer" mode. + * Do not change these settings unless you're working an advanced use case, like connecting to the Split proxy. + * @property {Object} urls + */ + urls?: UrlSettings, + } /** - * Destroy the client instance. - * @function destroy - * @returns {Promise} + * Common API for entities that expose status handlers. + * @interface IStatusInterface + * @extends IEventEmitter */ - destroy(): Promise -} -/****** Exposed namespace ******/ -/** - * Types and interfaces for @splitsoftware/splitio package for usage when integrating javascript sdk on typescript apps. - * For the SDK package information - * @see {@link https://www.npmjs.com/package/@splitsoftware/splitio} - */ -declare namespace SplitIO { + interface IStatusInterface extends IEventEmitter { + /** + * Constant object containing the SDK events for you to use. + * @property {EventConsts} Event + */ + Event: EventConsts, + /** + * Returns a promise that will be resolved once the SDK has finished loading (SDK_READY event emitted) or rejected if the SDK has timedout (SDK_READY_TIMED_OUT event emitted). + * As it's meant to provide similar flexibility to the event approach, given that the SDK might be eventually ready after a timeout event, calling the `ready` method after the + * SDK had timed out will return a new promise that should eventually resolve if the SDK gets ready. + * + * Caveats: the method was designed to avoid an unhandled Promise rejection if the rejection case is not handled, so that `onRejected` handler is optional when using promises. + * However, when using async/await syntax, the rejection should be explicitly propagated like in the following example: + * ``` + * try { + * await client.ready().catch((e) => { throw e; }); + * // SDK is ready + * } catch(e) { + * // SDK has timedout + * } + * ``` + * + * @function ready + * @returns {Promise} + */ + ready(): Promise + } /** - * NodeJS.EventEmitter interface - * @see {@link https://nodejs.org/api/events.html} + * Common definitions between clients for different environments interface. + * @interface IBasicClient + * @extends IStatusInterface */ - interface EventEmitter extends IEventEmitter { - addListener(event: string, listener: (...args: any[]) => void): this; - on(event: string, listener: (...args: any[]) => void): this; - once(event: string, listener: (...args: any[]) => void): this; - removeListener(event: string, listener: (...args: any[]) => void): this; - off(event: string, listener: (...args: any[]) => void): this; - removeAllListeners(event?: string): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string): Function[]; - rawListeners(event: string): Function[]; - emit(event: string, ...args: any[]): boolean; - listenerCount(type: string): number; - // Added in Node 6... - prependListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: string, listener: (...args: any[]) => void): this; - eventNames(): Array; + interface IBasicClient extends IStatusInterface { + /** + * Destroy the client instance. + * @function destroy + * @returns {Promise} + */ + destroy(): Promise } + /** * Split treatment value, returned by getTreatment. * @typedef {string} Treatment @@ -366,7 +364,7 @@ declare namespace SplitIO { [featureName: string]: Treatment }; /** - * Split treatments promise that will resolve to the actual SplitIO.Treatments object. + * Split treatments promise that will resolve to the actual Treatments object. * @typedef {Promise} AsyncTreatments */ type AsyncTreatments = Promise; @@ -398,7 +396,7 @@ declare namespace SplitIO { [featureName: string]: TreatmentWithConfig }; /** - * Split treatments promise that will resolve to the actual SplitIO.TreatmentsWithConfig object. + * Split treatments promise that will resolve to the actual TreatmentsWithConfig object. * @typedef {Promise} AsyncTreatmentsWithConfig */ type AsyncTreatmentsWithConfig = Promise; @@ -464,19 +462,10 @@ declare namespace SplitIO { * @typedef {Object} ImpressionData */ type ImpressionData = { - impression: { - feature: string, - keyName: string, - treatment: string, - time: number, - bucketingKey?: string, - label: string, - changeNumber: number, - pt?: number, - }, - attributes?: SplitIO.Attributes, - ip: string, - hostname: string, + impression: ImpressionDTO, + attributes?: Attributes, + ip: string | false, + hostname: string | false, sdkLanguageVersion: string }; /** @@ -524,11 +513,11 @@ declare namespace SplitIO { */ type SplitViewAsync = Promise; /** - * An array containing the SplitIO.SplitView elements. + * An array containing the SplitView elements. */ type SplitViews = Array; /** - * A promise that will be resolved with an SplitIO.SplitViews array. + * A promise that will be resolved with an SplitViews array. * @typedef {Promise} SplitViewsAsync */ type SplitViewsAsync = Promise; @@ -561,7 +550,7 @@ declare namespace SplitIO { * Storage for synchronous (standalone) SDK. * Its interface details are not part of the public API. */ - type StorageSync = {}; + type StorageSync = any; /** * Storage builder for synchronous (standalone) SDK. * By returning undefined, the SDK will use the default IN MEMORY storage. @@ -569,7 +558,7 @@ declare namespace SplitIO { */ type StorageSyncFactory = { readonly type: StorageType - (params: {}): (StorageSync | undefined) + (params: any): (StorageSync | undefined) } /** * Configuration params for `InLocalStorage` @@ -586,14 +575,14 @@ declare namespace SplitIO { * Storage for asynchronous (consumer) SDK. * Its interface details are not part of the public API. */ - type StorageAsync = {} + type StorageAsync = any /** * Storage builder for asynchronous (consumer) SDK. * Input parameter details are not part of the public API. */ type StorageAsyncFactory = { - readonly type: 'PLUGGABLE' - (params: {}): StorageAsync + readonly type: StorageType + (params: any): StorageAsync } /** * Configuration params for `PluggableStorage` @@ -617,7 +606,7 @@ declare namespace SplitIO { */ type LocalhostFactory = { readonly type: LocalhostType - (params: {}): {} + (params: any): any } /** * Impression listener interface. This is the interface that needs to be implemented @@ -626,13 +615,13 @@ declare namespace SplitIO { * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#listener} */ interface IImpressionListener { - logImpression(data: SplitIO.ImpressionData): void + logImpression(data: ImpressionData): void } /** * SDK integration instance. * Its interface details are not part of the public API. */ - type Integration = {}; + type Integration = any; /** * SDK integration factory. * By returning an integration, the SDK will queue events and impressions into it. @@ -640,7 +629,7 @@ declare namespace SplitIO { */ type IntegrationFactory = { readonly type: string - (params: {}): (Integration | void) + (params: any): (Integration | void) } /** * A pair of user key and it's trafficType, required for tracking valid Split events. @@ -704,7 +693,7 @@ declare namespace SplitIO { * return defaultMapping; * }` */ - mapper?: (model: UniversalAnalytics.Model, defaultMapping: SplitIO.EventData) => SplitIO.EventData, + mapper?: (model: UniversalAnalytics.Model, defaultMapping: EventData) => EventData, /** * Optional prefix for EventTypeId, to prevent any kind of data collision between events. * @property {string} prefix @@ -734,7 +723,7 @@ declare namespace SplitIO { * @property {string} type The type of Split data, either 'IMPRESSION' or 'EVENT'. * @property {ImpressionData | EventData} payload The data instance itself. */ - type IntegrationData = { type: 'IMPRESSION', payload: SplitIO.ImpressionData } | { type: 'EVENT', payload: SplitIO.EventData }; + type IntegrationData = { type: 'IMPRESSION', payload: ImpressionData } | { type: 'EVENT', payload: EventData }; /** * Enable 'Split to Google Analytics' integration, to track Split impressions and events as Google Analytics hits. * @@ -766,7 +755,7 @@ declare namespace SplitIO { * For example, the following filter allows to track only impressions, equivalent to setting events to false: * `(data) => data.type === 'IMPRESSION'` */ - filter?: (data: SplitIO.IntegrationData) => boolean, + filter?: (data: IntegrationData) => boolean, /** * Optional function useful when you need to modify the GA hit before sending it. * This function is invoked with two arguments: @@ -797,7 +786,7 @@ declare namespace SplitIO { * nonInteraction: true, * }` */ - mapper?: (data: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject, + mapper?: (data: IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject, /** * List of tracker names to send the hit. An empty string represents the default tracker. * If not provided, hits are only sent to default tracker. @@ -864,6 +853,11 @@ declare namespace SplitIO { */ values: string[], } + type ISplitFiltersValidation = { + queryString: string | null, + groupedFilters: Record, + validFilters: SplitFilter[] + }; /** * ImpressionsMode type * @typedef {string} ImpressionsMode @@ -881,11 +875,18 @@ declare namespace SplitIO { */ interface ILogger { setLogLevel(logLevel: LogLevel): void + debug(msg: any): void + debug(msg: string | number, args?: any[]): void + info(msg: any): void + info(msg: string | number, args?: any[]): void + warn(msg: any): void + warn(msg: string | number, args?: any[]): void + error(msg: any): void + error(msg: string | number, args?: any[]): void } /** * Common settings interface with non-pluggable API (JS SDK). * @interface IStaticSettings - * @extends ISharedSettings */ interface IStaticSettings { /** @@ -898,13 +899,13 @@ declare namespace SplitIO { /** * Common settings interface with pluggable API (JS Browser and React Native SDKs). * @interface IPluggableSettings - * @extends ISharedSettings */ interface IPluggableSettings { /** * Boolean value to indicate whether the logger should be enabled or disabled by default, or a log level string or a Logger object. * Passing a logger object is required to get descriptive log messages. Otherwise most logs will print with message codes. * @see {@link https://help.split.io/hc/en-us/articles/360058730852-Browser-SDK#logging} + * @see {@link https://help.split.io/hc/en-us/articles/4406066357901-React-Native-SDK#logging} * * Examples: * ```typescript @@ -915,20 +916,7 @@ declare namespace SplitIO { * @property {boolean | LogLevel | ILogger} debug * @default false */ - debug?: boolean | LogLevel | SplitIO.ILogger, - /** - * Defines an optional list of factory functions used to instantiate SDK integrations. - * - * Example: - * ```typescript - * SplitFactory({ - * ... - * integrations: [SplitToGoogleAnalytics(), GoogleAnalyticsToSplit()] - * }) - * ``` - * @property {Object} integrations - */ - integrations?: SplitIO.IntegrationFactory[], + debug?: boolean | LogLevel | ILogger, } /** * Common settings interface for SDK instances on NodeJS. @@ -954,7 +942,7 @@ declare namespace SplitIO { * @property {MockedFeaturesFilePath} features * @default $HOME/.split */ - features?: SplitIO.MockedFeaturesFilePath, + features?: MockedFeaturesFilePath, /** * SDK Startup settings for NodeJS. * @property {Object} startup @@ -1095,13 +1083,13 @@ declare namespace SplitIO { * Customer identifier. Whatever this means to you. @see {@link https://help.split.io/hc/en-us/articles/360019916311-Traffic-type} * @property {SplitKey} key */ - key: SplitIO.SplitKey, + key: SplitKey, }, /** * Mocked features map. For testing purposses only. For using this you should specify "localhost" as authorizationKey on core settings. * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#localhost-mode} */ - features?: SplitIO.MockedFeaturesMap, + features?: MockedFeaturesMap, /** * SDK Startup settings for client-side. * @property {Object} startup @@ -1236,7 +1224,7 @@ declare namespace SplitIO { * @typedef {string} userConsent * @default 'GRANTED' */ - userConsent?: SplitIO.ConsentStatus + userConsent?: ConsentStatus } /** * Common definitions between SDK instances for different environments interface. @@ -1246,13 +1234,13 @@ declare namespace SplitIO { /** * Returns the default client instance of the SDK. * @function client - * @returns {IClient} The client instance. + * @returns {TClient} The client instance. */ client(): TClient, /** * Returns a manager instance of the SDK to explore available information. * @function manager - * @returns {IManager} The manager instance. + * @returns {TManager} The manager instance. */ manager(): TManager /** @@ -1330,14 +1318,14 @@ declare namespace SplitIO { * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. * @returns {boolean} Whether the event was added to the queue successfully or not. */ - track(key: SplitIO.SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, + track(key: SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, } /** * This represents the interface for the Client instance with asynchronous method calls and server-side SDK, where we don't have only one key. * @interface IAsyncClient * @extends IBasicClient */ - interface IAsyncClienSS extends IBasicClient { + interface IAsyncClientSS extends IBasicClient { /** * Returns a Treatment value, which will be (or eventually be) the treatment string for the given feature. * For usage on NodeJS as we don't have only one key. @@ -1390,7 +1378,7 @@ declare namespace SplitIO { * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. * @returns {Promise} A promise that resolves to a boolean indicating if the event was added to the queue successfully or not. */ - track(key: SplitIO.SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): Promise + track(key: SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): Promise } /** * This represents the interface for the Client instance with attributes binding @@ -1424,7 +1412,7 @@ declare namespace SplitIO { * Add to client's in memory attributes storage the attributes in 'attributes'. * * @param {Attributes} attributes Object with attributes to store - * @returns true if attributes were stored an false otherwise + * @returns {boolean} true if attributes were stored an false otherwise */ setAttributes(attributes: Attributes): boolean, /** @@ -1489,33 +1477,6 @@ declare namespace SplitIO { */ track(trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, } - /** - * This represents the interface for the Client instance with attributes binding, synchronous method calls, and client-side API, where each client has a key associated and optionally a traffic type. - * @interface IClientWithKeyLegacy - * @extends IClientWithKey - */ - interface IClientWithKeyLegacy extends IClientWithKey { - /** - * Tracks an event to be fed to the results product on Split Webconsole. - * @function track - * @param {string} trafficType - The traffic type of the entity related to this event. - * @param {string} eventType - The event type corresponding to this event. - * @param {number=} value - The value of this event. - * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. - * @returns {boolean} Whether the event was added to the queue successfully or not. - */ - track(trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, - /** - * Tracks an event to be fed to the results product on Split Webconsole. - * For usage on the Browser if we defined the key and also the trafficType on the settings. - * @function track - * @param {string} eventType - The event type corresponding to this event. - * @param {number=} value - The value of this event. - * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. - * @returns {boolean} Whether the event was added to the queue successfully or not. - */ - track(eventType: string, value?: number, properties?: Properties): boolean - } /** * This represents the interface for the Client instance with attributes binding, asynchronous method calls, and client-side API, where each client has a key associated. * @interface IAsyncClientWithKey @@ -1561,7 +1522,7 @@ declare namespace SplitIO { * @param {string} eventType - The event type corresponding to this event. * @param {number=} value - The value of this event. * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. - * @returns {boolean} A promise that resolves to a boolean indicating if the event was added to the queue successfully or not. + * @returns {Promise} A promise that resolves to a boolean indicating if the event was added to the queue successfully or not. */ track(trafficType: string, eventType: string, value?: number, properties?: Properties): Promise, } @@ -1580,14 +1541,14 @@ declare namespace SplitIO { /** * Get the array of splits data in SplitView format. * @function splits - * @returns {SplitViews} The list of SplitIO.SplitView. + * @returns {SplitViews} The list of SplitView. */ splits(): SplitViews; /** * Get the data of a split in SplitView format. * @function split * @param {string} splitName The name of the split we wan't to get info of. - * @returns {SplitView | null} The SplitIO.SplitView of the given split or null if the split is not found. + * @returns {SplitView | null} The SplitView of the given split or null if the split is not found. */ split(splitName: string): SplitView | null; } @@ -1606,14 +1567,14 @@ declare namespace SplitIO { /** * Get the array of splits data in SplitView format. * @function splits - * @returns {SplitViewsAsync} A promise that will resolve to the SplitIO.SplitView list. + * @returns {SplitViewsAsync} A promise that will resolve to the SplitView list. */ splits(): SplitViewsAsync; /** * Get the data of a split in SplitView format. * @function split * @param {string} splitName The name of the split we wan't to get info of. - * @returns {SplitViewAsync} A promise that will resolve to the SplitIO.SplitView value or null if the split is not found. + * @returns {SplitViewAsync} A promise that will resolve to the SplitView value or null if the split is not found. */ split(splitName: string): SplitViewAsync; } diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index a45c27a7..00000000 --- a/src/types.ts +++ /dev/null @@ -1,1263 +0,0 @@ -import { ISplitFiltersValidation } from './dtos/types'; -import { IIntegration, IIntegrationFactoryParams } from './integrations/types'; -import { ILogger } from './logger/types'; -import { ISdkFactoryContext } from './sdkFactory/types'; -/* eslint-disable no-use-before-define */ - -import { IStorageFactoryParams, IStorageSync, IStorageAsync, IStorageSyncFactory, IStorageAsyncFactory } from './storages/types'; -import { ISyncManagerCS } from './sync/types'; - -/** - * Reduced version of NodeJS.EventEmitter interface with the minimal methods used by the SDK - * @see {@link https://nodejs.org/api/events.html} - */ -export interface IEventEmitter { - addListener(event: string, listener: (...args: any[]) => void): this; - on(event: string, listener: (...args: any[]) => void): this - once(event: string, listener: (...args: any[]) => void): this - removeListener(event: string, listener: (...args: any[]) => void): this; - off(event: string, listener: (...args: any[]) => void): this; - removeAllListeners(event?: string): this - emit(event: string, ...args: any[]): boolean -} - -/** - * impression DTO generated by the Sdk client when processing evaluations - */ -export type ImpressionDTO = { - feature: string, - keyName: string, - treatment: string, - time: number, - bucketingKey?: string, - label: string, - changeNumber: number, - pt?: number, -} - -/** splitio.d.ts */ - -/** - * @typedef {Object} EventConsts - * @property {string} SDK_READY The ready event. - * @property {string} SDK_READY_FROM_CACHE The ready event when fired with cached data. - * @property {string} SDK_READY_TIMED_OUT The timeout event. - * @property {string} SDK_UPDATE The update event. - */ -type EventConsts = { - SDK_READY: 'init::ready', - SDK_READY_FROM_CACHE: 'init::cache-ready', - SDK_READY_TIMED_OUT: 'init::timeout', - SDK_UPDATE: 'state::update' -}; -/** - * SDK Modes. - * @typedef {string} SDKMode - */ -export type SDKMode = 'standalone' | 'consumer' | 'localhost' | 'consumer_partial'; -/** - * User consent status. - * @typedef {string} ConsentStatus - */ -export type ConsentStatus = 'GRANTED' | 'DECLINED' | 'UNKNOWN'; -/** - * Settings interface. This is a representation of the settings the SDK expose, that's why - * most of it's props are readonly. Only features should be rewritten when localhost mode is active. - * @interface ISettings - * - * NOTE: same ISettings interface from public type declarations extended with private properties. - */ -export interface ISettings { - readonly core: { - authorizationKey: string, - key: SplitIO.SplitKey, - trafficType?: string, - labelsEnabled: boolean, - IPAddressesEnabled: boolean - }, - readonly mode: SDKMode, - readonly scheduler: { - featuresRefreshRate: number, - impressionsRefreshRate: number, - impressionsQueueSize: number, - /** - * @deprecated - */ - metricsRefreshRate?: number, - telemetryRefreshRate: number, - segmentsRefreshRate: number, - offlineRefreshRate: number, - eventsPushRate: number, - eventsQueueSize: number, - pushRetryBackoffBase: number - }, - readonly startup: { - readyTimeout: number, - requestTimeoutBeforeReady: number, - retriesOnFailureBeforeReady: number, - eventsFirstPushWindow: number - }, - readonly storage: IStorageSyncFactory | IStorageAsyncFactory, - readonly integrations: Array<{ - readonly type: string, - (params: IIntegrationFactoryParams): IIntegration | void - }>, - readonly urls: { - events: string, - sdk: string, - auth: string, - streaming: string, - telemetry: string - }, - readonly debug: boolean | LogLevel | ILogger, - readonly version: string, - features: SplitIO.MockedFeaturesFilePath | SplitIO.MockedFeaturesMap, - readonly streamingEnabled: boolean, - readonly sync: { - splitFilters: SplitIO.SplitFilter[], - impressionsMode: SplitIO.ImpressionsMode, - __splitFiltersValidation: ISplitFiltersValidation, - localhostMode?: SplitIO.LocalhostFactory, - enabled: boolean - }, - readonly runtime: { - ip: string | false - hostname: string | false - }, - readonly log: ILogger - readonly impressionListener?: unknown - readonly userConsent?: ConsentStatus -} -/** - * Log levels. - * @typedef {string} LogLevel - */ -export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE'; -/** - * Logger API - * @interface ILoggerAPI - */ -export interface ILoggerAPI { - /** - * Enables SDK logging to the console. - * @function enable - * @returns {void} - */ - enable(): void, - /** - * Disables SDK logging. - * @function disable - * @returns {void} - */ - disable(): void, - /** - * Sets a log level for the SDK logs. - * @function setLogLevel - * @returns {void} - */ - setLogLevel(logLevel: LogLevel): void, - /** - * Log level constants. Use this to pass them to setLogLevel function. - */ - LogLevel: { - [level: string]: LogLevel - } -} -/** - * Common settings between Browser and NodeJS settings interface. - * @interface ISharedSettings - */ -interface ISharedSettings { - /** - * Whether the logger should be enabled or disabled by default. - * @property {Boolean} debug - * @default false - */ - debug?: boolean, - /** - * The impression listener, which is optional. Whatever you provide here needs to comply with the SplitIO.IImpressionListener interface, - * which will check for the logImpression method. - * @property {IImpressionListener} impressionListener - * @default undefined - */ - impressionListener?: SplitIO.IImpressionListener, - /** - * Boolean flag to enable the streaming service as default synchronization mechanism. In the event of any issue with streaming, - * the SDK would fallback to the polling mechanism. If false, the SDK would poll for changes as usual without attempting to use streaming. - * @property {boolean} streamingEnabled - * @default true - */ - streamingEnabled?: boolean, - /** - * SDK synchronization settings. - * @property {Object} sync - */ - sync?: { - /** - * List of Split filters. These filters are used to fetch a subset of the Splits definitions in your environment, in order to reduce the delay of the SDK to be ready. - * This configuration is only meaningful when the SDK is working in "standalone" mode. - * - * At the moment, two types of split filters are supported: by name and by prefix. - * Example: - * `splitFilter: [ - * { type: 'byName', values: ['my_split_1', 'my_split_2'] }, // will fetch splits named 'my_split_1' and 'my_split_2' - * { type: 'byPrefix', values: ['testing'] } // will fetch splits whose names start with 'testing__' prefix - * ]` - * @property {SplitIO.SplitFilter[]} splitFilters - */ - splitFilters?: SplitIO.SplitFilter[] - /** - * Impressions Collection Mode. Option to determine how impressions are going to be sent to Split Servers. - * Possible values are 'DEBUG' and 'OPTIMIZED'. - * - DEBUG: will send all the impressions generated (recommended only for debugging purposes). - * - OPTIMIZED: will send unique impressions to Split Servers avoiding a considerable amount of traffic that duplicated impressions could generate. - * @property {String} impressionsMode - * @default 'OPTIMIZED' - */ - impressionsMode?: SplitIO.ImpressionsMode, - /** - * Enables synchronization. - * @property {boolean} enabled - */ - enabled: boolean - } -} -/** - * Common settings interface for SDK instances on NodeJS. - * @interface INodeBasicSettings - * @extends ISharedSettings - */ -interface INodeBasicSettings extends ISharedSettings { - /** - * SDK Startup settings for NodeJS. - * @property {Object} startup - */ - startup?: { - /** - * Maximum amount of time used before notify a timeout. - * @property {number} readyTimeout - * @default 15 - */ - readyTimeout?: number, - /** - * Time to wait for a request before the SDK is ready. If this time expires, JS Sdk will retry 'retriesOnFailureBeforeReady' times before notifying its failure to be 'ready'. - * @property {number} requestTimeoutBeforeReady - * @default 15 - */ - requestTimeoutBeforeReady?: number, - /** - * How many quick retries we will do while starting up the SDK. - * @property {number} retriesOnFailureBeforeReady - * @default 1 - */ - retriesOnFailureBeforeReady?: number, - /** - * For SDK posts the queued events data in bulks with a given rate, but the first push window is defined separately, - * to better control on browsers. This number defines that window before the first events push. - * - * @property {number} eventsFirstPushWindow - * @default 0 - */ - eventsFirstPushWindow?: number, - }, - /** - * SDK scheduler settings. - * @property {Object} scheduler - */ - scheduler?: { - /** - * The SDK polls Split servers for changes to feature roll-out plans. This parameter controls this polling period in seconds. - * @property {number} featuresRefreshRate - * @default 5 - */ - featuresRefreshRate?: number, - /** - * The SDK sends information on who got what treatment at what time back to Split servers to power analytics. This parameter controls how often this data is sent to Split servers. The parameter should be in seconds. - * @property {number} impressionsRefreshRate - * @default 300 - */ - impressionsRefreshRate?: number, - /** - * The maximum number of impression items we want to queue. If we queue more values, it will trigger a flush and reset the timer. - * If you use a 0 here, the queue will have no maximum size. - * @property {number} impressionsQueueSize - * @default 30000 - */ - impressionsQueueSize?: number, - /** - * The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds. - * @property {number} metricsRefreshRate - * @default 120 - * @deprecated This parameter is ignored now. - */ - metricsRefreshRate?: number, - /** - * The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds. - * @property {number} telemetryRefreshRate - * @default 3600 - */ - telemetryRefreshRate?: number, - /** - * The SDK polls Split servers for changes to segment definitions. This parameter controls this polling period in seconds. - * @property {number} segmentsRefreshRate - * @default 60 - */ - segmentsRefreshRate?: number, - /** - * The SDK posts the queued events data in bulks. This parameter controls the posting rate in seconds. - * @property {number} eventsPushRate - * @default 60 - */ - eventsPushRate?: number, - /** - * The maximum number of event items we want to queue. If we queue more values, it will trigger a flush and reset the timer. - * If you use a 0 here, the queue will have no maximum size. - * @property {number} eventsQueueSize - * @default 500 - */ - eventsQueueSize?: number, - /** - * For mocking/testing only. The SDK will refresh the features mocked data when mode is set to "localhost" by defining the key. - * For more information @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#localhost-mode} - * @property {number} offlineRefreshRate - * @default 15 - */ - offlineRefreshRate?: number - /** - * When using streaming mode, seconds to wait before re attempting to connect for push notifications. - * Next attempts follow intervals in power of two: base seconds, base x 2 seconds, base x 4 seconds, ... - * @property {number} pushRetryBackoffBase - * @default 1 - */ - pushRetryBackoffBase?: number, - }, - /** - * SDK Core settings for NodeJS. - * @property {Object} core - */ - core: { - /** - * Your API key. More information: @see {@link https://help.split.io/hc/en-us/articles/360019916211-API-keys} - * @property {string} authorizationKey - */ - authorizationKey: string, - /** - * Disable labels from being sent to Split backend. Labels may contain sensitive information. - * @property {boolean} labelsEnabled - * @default true - */ - labelsEnabled?: boolean - /** - * Disable machine IP and Name from being sent to Split backend. - * @property {boolean} IPAddressesEnabled - * @default true - */ - IPAddressesEnabled?: boolean - }, - /** - * Defines which kind of storage we should instanciate. - * @property {Object} storage - */ - storage?: (params: any) => any, - /** - * The SDK mode. Possible values are "standalone" (which is the default) and "consumer". For "localhost" mode, use "localhost" as authorizationKey. - * @property {SDKMode} mode - * @default standalone - */ - mode?: SDKMode, - /** - * Mocked features file path. For testing purposses only. For using this you should specify "localhost" as authorizationKey on core settings. - * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#localhost-mode} - * @property {MockedFeaturesFilePath} features - * @default $HOME/.split - */ - features?: SplitIO.MockedFeaturesFilePath, -} -/** - * Common API for entities that expose status handlers. - * @interface IStatusInterface - * @extends IEventEmitter - */ -export interface IStatusInterface extends IEventEmitter { - /** - * Constant object containing the SDK events for you to use. - * @property {EventConsts} Event - */ - Event: EventConsts, - /** - * Returns a promise that will be resolved once the SDK has finished loading (SDK_READY event emitted) or rejected if the SDK has timedout (SDK_READY_TIMED_OUT event emitted). - * As it's meant to provide similar flexibility to the event approach, given that the SDK might be eventually ready after a timeout event, calling the `ready` method after the - * SDK had timed out will return a new promise that should eventually resolve if the SDK gets ready. - * - * Caveats: the method was designed to avoid an unhandled Promise rejection if the rejection case is not handled, so that `onRejected` handler is optional when using promises. - * However, when using async/await syntax, the rejection should be explicitly propagated like in the following example: - * ``` - * try { - * await client.ready().catch((e) => { throw e; }); - * // SDK is ready - * } catch(e) { - * // SDK has timedout - * } - * ``` - * - * @function ready - * @returns {Promise} - */ - ready(): Promise -} -/** - * Common definitions between clients for different environments interface. - * @interface IBasicClient - * @extends IStatusInterface - */ -interface IBasicClient extends IStatusInterface { - /** - * Destroy the client instance. - * @function destroy - * @returns {Promise} - */ - destroy(): Promise - - // Whether the client implements the client-side API, i.e, with bound key, (true), or the server-side API (false). - // Exposed for internal purposes only. Not considered part of the public API, and might be renamed eventually. - isClientSide: boolean -} -/** - * Common definitions between SDK instances for different environments interface. - * @interface IBasicSDK - */ -interface IBasicSDK { - /** - * Current settings of the SDK instance. - * @property settings - */ - settings: ISettings, - /** - * Logger API. - * @property Logger - */ - Logger: ILoggerAPI -} -/****** Exposed namespace ******/ -/** - * Types and interfaces for @splitsoftware/splitio package for usage when integrating javascript sdk on typescript apps. - * For the SDK package information - * @see {@link https://www.npmjs.com/package/@splitsoftware/splitio} - */ -export namespace SplitIO { - /** - * Split treatment value, returned by getTreatment. - * @typedef {string} Treatment - */ - export type Treatment = string; - /** - * Split treatment promise that will resolve to actual treatment value. - * @typedef {Promise} AsyncTreatment - */ - export type AsyncTreatment = Promise; - /** - * An object with the treatments for a bulk of splits, returned by getTreatments. For example: - * { - * feature1: 'on', - * feature2: 'off - * } - * @typedef {Object.} Treatments - */ - export type Treatments = { - [featureName: string]: Treatment - }; - /** - * Split treatments promise that will resolve to the actual SplitIO.Treatments object. - * @typedef {Promise} AsyncTreatments - */ - export type AsyncTreatments = Promise; - /** - * Split evaluation result with treatment and configuration, returned by getTreatmentWithConfig. - * @typedef {Object} TreatmentWithConfig - * @property {string} treatment The treatment result - * @property {string | null} config The stringified version of the JSON config defined for that treatment, null if there is no config for the resulting treatment. - */ - export type TreatmentWithConfig = { - treatment: string, - config: string | null - }; - /** - * Split treatment promise that will resolve to actual treatment with config value. - * @typedef {Promise} AsyncTreatmentWithConfig - */ - export type AsyncTreatmentWithConfig = Promise; - /** - * An object with the treatments with configs for a bulk of splits, returned by getTreatmentsWithConfig. - * Each existing configuration is a stringified version of the JSON you defined on the Split web console. For example: - * { - * feature1: { treatment: 'on', config: null } - * feature2: { treatment: 'off', config: '{"bannerText":"Click here."}' } - * } - * @typedef {Object.} Treatments - */ - export type TreatmentsWithConfig = { - [featureName: string]: TreatmentWithConfig - }; - /** - * Split treatments promise that will resolve to the actual SplitIO.TreatmentsWithConfig object. - * @typedef {Promise} AsyncTreatmentsWithConfig - */ - export type AsyncTreatmentsWithConfig = Promise; - /** - * Possible Split SDK events. - * @typedef {string} Event - */ - export type Event = 'init::timeout' | 'init::ready' | 'init::cache-ready' | 'state::update'; - /** - * Split attributes should be on object with values of type string or number (dates should be sent as millis since epoch). - * @typedef {Object.} Attributes - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#attribute-syntax} - */ - export type Attributes = { - [attributeName: string]: string | number | boolean | Array - }; - /** - * Split properties should be an object with values of type string, number, boolean or null. Size limit of ~31kb. - * @typedef {Object.} Attributes - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#track - */ - export type Properties = { - [propertyName: string]: string | number | boolean | null - }; - /** - * The SplitKey object format. - * @typedef {Object.} SplitKeyObject - */ - export type SplitKeyObject = { - matchingKey: string, - bucketingKey: string - }; - /** - * The customer identifier. Could be a SplitKeyObject or a string. - * @typedef {SplitKeyObject|string} SplitKey - */ - export type SplitKey = SplitKeyObject | string; - /** - * Path to file with mocked features (for node). - * @typedef {string} MockedFeaturesFilePath - */ - export type MockedFeaturesFilePath = string; - /** - * Object with mocked features mapping (for browser). We need to specify the featureName as key, and the mocked treatment as value. - * @typedef {Object} MockedFeaturesMap - */ - export type MockedFeaturesMap = { - [featureName: string]: string | TreatmentWithConfig - }; - /** - * Object with information about an impression. It contains the generated impression DTO as well as - * complementary information around where and how it was generated in that way. - * @typedef {Object} ImpressionData - */ - export type ImpressionData = { - impression: ImpressionDTO, - attributes?: SplitIO.Attributes, - ip: string| false, - hostname: string | false, - sdkLanguageVersion: string - }; - /** - * Data corresponding to one Split view. - * @typedef {Object} SplitView - */ - export type SplitView = { - /** - * The name of the split. - * @property {string} name - */ - name: string, - /** - * The traffic type of the split. - * @property {string} trafficType - */ - trafficType: string, - /** - * Whether the split is killed or not. - * @property {boolean} killed - */ - killed: boolean, - /** - * The list of treatments available for the split. - * @property {Array} treatments - */ - treatments: Array, - /** - * Current change number of the split. - * @property {number} changeNumber - */ - changeNumber: number, - /** - * Map of configurations per treatment. - * Each existing configuration is a stringified version of the JSON you defined on the Split web console. - * @property {Object.} configs - */ - configs: { - [treatmentName: string]: string - } - }; - /** - * A promise that will be resolved with that SplitView. - * @typedef {Promise} SplitView - */ - export type SplitViewAsync = Promise; - /** - * An array containing the SplitIO.SplitView elements. - */ - export type SplitViews = Array; - /** - * A promise that will be resolved with an SplitIO.SplitViews array. - * @typedef {Promise} SplitViewsAsync - */ - export type SplitViewsAsync = Promise; - /** - * An array of split names. - * @typedef {Array} SplitNames - */ - export type SplitNames = Array; - /** - * A promise that will be resolved with an array of split names. - * @typedef {Promise} SplitNamesAsync - */ - export type SplitNamesAsync = Promise; - /** - * Localhost mode factory. - */ - export type LocalhostFactory = { - type: 'LocalhostFromObject' | 'LocalhostFromFile' - (params: ISdkFactoryContext): ISyncManagerCS - } - /** - * Impression listener interface. This is the interface that needs to be implemented - * by the element you provide to the SDK as impression listener. - * @interface IImpressionListener - * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#listener} - */ - export interface IImpressionListener { - logImpression(data: SplitIO.ImpressionData): void - } - /** - * Object with information about a Split event. - * @typedef {Object} EventData - */ - export type EventData = { - eventTypeId: string; - value?: number; - properties?: Properties; - trafficTypeName?: string; - key?: string; // matching user key - timestamp: number; - }; - /** - * Object representing the data sent by Split (events and impressions). - * @typedef {Object} IntegrationData - * @property {string} type The type of Split data, either 'IMPRESSION' or 'EVENT'. - * @property {ImpressionData | EventData} payload The data instance itself. - */ - export type IntegrationData = { type: 'IMPRESSION', payload: SplitIO.ImpressionData } | { type: 'EVENT', payload: SplitIO.EventData }; - /** - * Available URL settings for the SDKs. - */ - export type UrlSettings = { - /** - * String property to override the base URL where the SDK will get feature flagging related data like a Split rollout plan or segments information. - * @property {string} sdk - * @default 'https://sdk.split.io/api' - */ - sdk?: string, - /** - * String property to override the base URL where the SDK will post event-related information like impressions. - * @property {string} events - * @default 'https://events.split.io/api' - */ - events?: string, - /** - * String property to override the base URL where the SDK will get authorization tokens to be used with functionality that requires it, like streaming. - * @property {string} auth - * @default 'https://auth.split.io/api' - */ - auth?: string, - /** - * String property to override the base URL where the SDK will connect to receive streaming updates. - * @property {string} streaming - * @default 'https://streaming.split.io' - */ - streaming?: string, - /** - * String property to override the base URL where the SDK will post telemetry data. - * @property {string} telemetry - * @default 'https://telemetry.split.io/api' - */ - telemetry?: string - }; - /** - * SplitFilter type. - * @typedef {string} SplitFilterType - */ - export type SplitFilterType = 'byName' | 'byPrefix'; - /** - * Defines a split filter, described by a type and list of values. - */ - export interface SplitFilter { - /** - * Type of the filter. - * @property {SplitFilterType} type - */ - type: SplitFilterType, - /** - * List of values: split names for 'byName' filter type, and split prefixes for 'byPrefix' type. - * @property {string[]} values - */ - values: string[], - } - /** - * ImpressionsMode type - * @typedef {string} ImpressionsMode - */ - export type ImpressionsMode = 'OPTIMIZED' | 'DEBUG' - /** - * Defines the format of Split data to preload on the factory storage (cache). - */ - export interface PreloadedData { - /** - * Timestamp of the last moment the data was synchronized with Split servers. - * If this value is older than 10 days ago (expiration time policy), the data is not used to update the storage content. - * @TODO configurable expiration time policy? - */ - lastUpdated: number, - /** - * Change number of the preloaded data. - * If this value is older than the current changeNumber at the storage, the data is not used to update the storage content. - */ - since: number, - /** - * Map of splits to their serialized definitions. - */ - splitsData: { - [splitName: string]: string - }, - /** - * Optional map of user keys to their list of segments. - * @TODO remove when releasing first version - */ - mySegmentsData?: { - [key: string]: string[] - }, - /** - * Optional map of segments to their serialized definitions. - * This property is ignored if `mySegmentsData` was provided. - */ - segmentsData?: { - [segmentName: string]: string - }, - } - /** - * Settings interface for SDK instances created on the browser - * @interface IBrowserSettings - * @extends ISharedSettings - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration} - */ - export interface IBrowserSettings extends ISharedSettings { - /** - * SDK Startup settings for the Browser. - * @property {Object} startup - */ - startup?: { - /** - * Maximum amount of time used before notify a timeout. - * @property {number} readyTimeout - * @default 1.5 - */ - readyTimeout?: number, - /** - * Time to wait for a request before the SDK is ready. If this time expires, JS Sdk will retry 'retriesOnFailureBeforeReady' times before notifying its failure to be 'ready'. - * @property {number} requestTimeoutBeforeReady - * @default 1.5 - */ - requestTimeoutBeforeReady?: number, - /** - * How many quick retries we will do while starting up the SDK. - * @property {number} retriesOnFailureBeforeReady - * @default 1 - */ - retriesOnFailureBeforeReady?: number, - /** - * For SDK posts the queued events data in bulks with a given rate, but the first push window is defined separately, - * to better control on browsers. This number defines that window before the first events push. - * - * @property {number} eventsFirstPushWindow - * @default 10 - */ - eventsFirstPushWindow?: number, - }, - /** - * SDK scheduler settings. - * @property {Object} scheduler - */ - scheduler?: { - /** - * The SDK polls Split servers for changes to feature roll-out plans. This parameter controls this polling period in seconds. - * @property {number} featuresRefreshRate - * @default 30 - */ - featuresRefreshRate?: number, - /** - * The SDK sends information on who got what treatment at what time back to Split servers to power analytics. This parameter controls how often this data is sent to Split servers. The parameter should be in seconds. - * @property {number} impressionsRefreshRate - * @default 60 - */ - impressionsRefreshRate?: number, - /** - * The maximum number of impression items we want to queue. If we queue more values, it will trigger a flush and reset the timer. - * If you use a 0 here, the queue will have no maximum size. - * @property {number} impressionsQueueSize - * @default 30000 - */ - impressionsQueueSize?: number, - /** - * The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds. - * @property {number} metricsRefreshRate - * @default 120 - * @deprecated This parameter is ignored now. - */ - metricsRefreshRate?: number, - /** - * The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds. - * @property {number} telemetryRefreshRate - * @default 3600 - */ - telemetryRefreshRate?: number, - /** - * The SDK polls Split servers for changes to segment definitions. This parameter controls this polling period in seconds. - * @property {number} segmentsRefreshRate - * @default 60 - */ - segmentsRefreshRate?: number, - /** - * The SDK posts the queued events data in bulks. This parameter controls the posting rate in seconds. - * @property {number} eventsPushRate - * @default 60 - */ - eventsPushRate?: number, - /** - * The maximum number of event items we want to queue. If we queue more values, it will trigger a flush and reset the timer. - * If you use a 0 here, the queue will have no maximum size. - * @property {number} eventsQueueSize - * @default 500 - */ - eventsQueueSize?: number, - /** - * For mocking/testing only. The SDK will refresh the features mocked data when mode is set to "localhost" by defining the key. - * For more information @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#localhost-mode} - * @property {number} offlineRefreshRate - * @default 15 - */ - offlineRefreshRate?: number - /** - * When using streaming mode, seconds to wait before re attempting to connect for push notifications. - * Next attempts follow intervals in power of two: base seconds, base x 2 seconds, base x 4 seconds, ... - * @property {number} pushRetryBackoffBase - * @default 1 - */ - pushRetryBackoffBase?: number, - }, - /** - * SDK Core settings for the browser. - * @property {Object} core - */ - core: { - /** - * Your API key. More information: @see {@link https://help.split.io/hc/en-us/articles/360019916211-API-keys} - * @property {string} authorizationKey - */ - authorizationKey: string, - /** - * Customer identifier. Whatever this means to you. @see {@link https://help.split.io/hc/en-us/articles/360019916311-Traffic-type} - * @property {SplitKey} key - */ - key: SplitKey, - /** - * Traffic type associated with the customer identifier. @see {@link https://help.split.io/hc/en-us/articles/360019916311-Traffic-type} - * If no provided as a setting it will be required on the client.track() calls. - * @property {string} trafficType - */ - trafficType?: string, - /** - * Disable labels from being sent to Split backend. Labels may contain sensitive information. - * @property {boolean} labelsEnabled - * @default true - */ - labelsEnabled?: boolean - }, - /** - * Mocked features map. For testing purposses only. For using this you should specify "localhost" as authorizationKey on core settings. - * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#localhost-mode} - */ - features?: MockedFeaturesMap, - /** - * Defines which kind of storage we should instanciate. - * @property {Object} storage - */ - storage?: (params: IStorageFactoryParams) => IStorageSync | IStorageAsync, - /** - * List of URLs that the SDK will use as base for it's synchronization functionalities, applicable only when running as standalone. - * Do not change these settings unless you're working an advanced use case, like connecting to the Split proxy. - * @property {Object} urls - */ - urls?: UrlSettings, - } - /** - * Settings interface for SDK instances created on NodeJS. - * If your storage is asynchronous (Redis for example) use SplitIO.INodeAsyncSettings instead. - * @interface INodeSettings - * @extends INodeBasicSettings - * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} - */ - export interface INodeSettings extends INodeBasicSettings { - /** - * List of URLs that the SDK will use as base for it's synchronization functionalities, applicable only when running as standalone. - * Do not change these settings unless you're working an advanced use case, like connecting to the Split proxy. - * @property {Object} urls - */ - urls?: UrlSettings, - /** - * Defines which kind of storage we should instanciate. - * @property {Object} storage - */ - storage?: (params: IStorageFactoryParams) => IStorageSync, - } - /** - * Settings interface with async storage for SDK instances created on NodeJS. - * If your storage is synchronous (by defaut we use memory, which is sync) use SplitIO.INodeSyncSettings instead. - * @interface INodeAsyncSettings - * @extends INodeBasicSettings - * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} - */ - export interface INodeAsyncSettings extends INodeBasicSettings { - storage?: (params: IStorageFactoryParams) => IStorageAsync, - } - /** - * This represents the interface for the Server-side SDK instance with synchronous storage. - * @interface ISDK - * @extends IBasicSDK - */ - export interface ISDK extends IBasicSDK { - /** - * Returns the client instance of the SDK. - * @function client - * @returns {IClient} The client instance. - */ - client(): IClient, - /** - * Returns a manager instance of the SDK to explore available information. - * @function manager - * @returns {IManager} The manager instance. - */ - manager(): IManager - } - /** - * This represents the interface for the Server-side SDK instance with asynchronous storage. - * @interface IAsyncSDK - * @extends IBasicSDK - */ - export interface IAsyncSDK extends IBasicSDK { - /** - * Returns the default client instance of the SDK. - * @function client - * @returns {IAsyncClient} The asynchronous client instance. - */ - client(): IAsyncClient, - /** - * Returns a manager instance of the SDK to explore available information. - * @function manager - * @returns {IManager} The manager instance. - */ - manager(): IAsyncManager - } - /** - * This represents the interface for the Client-side SDK instance with synchronous storage. - * @interface ICsSDK - * @extends IBasicSDK - */ - export interface ICsSDK extends IBasicSDK { - /** - * Returns the default client instance of the SDK, with the key and optional traffic type from settings. - * @function client - * @returns {ICsClient} The client instance. - */ - client(): ICsClient, - /** - * Returns a shared client of the SDK, with the given key and optional traffic type. - * @function client - * @param {SplitKey} key The key for the new client instance. - * @param {string=} trafficType The traffic type of the provided key. - * @returns {ICsClient} The client instance. - */ - client(key: SplitKey, trafficType?: string): ICsClient, - /** - * Returns a manager instance of the SDK to explore available information. - * @function manager - * @returns {IManager} The manager instance. - */ - manager(): IManager - } - /** - * This represents the interface for the Client instance with synchronous storage for server-side SDK, where we don't have only one key. - * @interface IClient - * @extends IBasicClient - */ - export interface IClient extends IBasicClient { - /** - * Returns a Treatment value, which will be (or eventually be) the treatment string for the given feature. - * @function getTreatment - * @param {string} key - The string key representing the consumer. - * @param {string} splitName - The string that represents the split we wan't to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatment} The treatment or treatment promise which will resolve to the treatment string. - */ - getTreatment(key: SplitKey, splitName: string, attributes?: Attributes): Treatment, - /** - * Returns a TreatmentWithConfig value (a map of treatment and config), which will be (or eventually be) the map with treatment and config for the given feature. - * @function getTreatmentWithConfig - * @param {string} key - The string key representing the consumer. - * @param {string} splitName - The string that represents the split we wan't to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {TreatmentWithConfig} The TreatmentWithConfig or TreatmentWithConfig promise which will resolve to the map containing - * the treatment and the configuration stringified JSON (or null if there was no config for that treatment). - */ - getTreatmentWithConfig(key: SplitKey, splitName: string, attributes?: Attributes): TreatmentWithConfig, - /** - * Returns a Treatments value, whick will be (or eventually be) an object with the treatments for the given features. - * @function getTreatments - * @param {string} key - The string key representing the consumer. - * @param {Array} splitNames - An array of the split names we wan't to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The treatments or treatments promise which will resolve to the treatments object. - */ - getTreatments(key: SplitKey, splitNames: string[], attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, whick will be an object with the TreatmentWithConfig (a map with both treatment and config string) for the given features. - * @function getTreatmentsWithConfig - * @param {string} key - The string key representing the consumer. - * @param {Array} splitNames - An array of the split names we wan't to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {TreatmentsWithConfig} The map with all the TreatmentWithConfig objects - */ - getTreatmentsWithConfig(key: SplitKey, splitNames: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Tracks an event to be fed to the results product on Split Webconsole. - * @function track - * @param {SplitKey} key - The key that identifies the entity related to this event. - * @param {string} trafficType - The traffic type of the entity related to this event. - * @param {string} eventType - The event type corresponding to this event. - * @param {number=} value - The value of this event. - * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. - * @returns {boolean} Whether the event was added to the queue succesfully or not. - */ - track(key: SplitIO.SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, - } - /** - * This represents the interface for the Client instance with asynchronous storage for server-side SDK, where we don't have only one key. - * @interface IAsyncClient - * @extends IBasicClient - */ - export interface IAsyncClient extends IBasicClient { - /** - * Returns a Treatment value, which will be (or eventually be) the treatment string for the given feature. - * For usage on NodeJS as we don't have only one key. - * NOTE: Treatment will be a promise only in async storages, like REDIS. - * @function getTreatment - * @param {string} key - The string key representing the consumer. - * @param {string} splitName - The string that represents the split we wan't to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatment} Treatment promise which will resolve to the treatment string. - */ - getTreatment(key: SplitKey, splitName: string, attributes?: Attributes): AsyncTreatment, - /** - * Returns a TreatmentWithConfig value, which will be (or eventually be) a map with both treatment and config string for the given feature. - * For usage on NodeJS as we don't have only one key. - * NOTE: Treatment will be a promise only in async storages, like REDIS. - * @function getTreatmentWithConfig - * @param {string} key - The string key representing the consumer. - * @param {string} splitName - The string that represents the split we wan't to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatmentWithConfig} TreatmentWithConfig promise which will resolve to the TreatmentWithConfig object. - */ - getTreatmentWithConfig(key: SplitKey, splitName: string, attributes?: Attributes): AsyncTreatmentWithConfig, - /** - * Returns a Treatments value, whick will be (or eventually be) an object with the treatments for the given features. - * For usage on NodeJS as we don't have only one key. - * @function getTreatments - * @param {string} key - The string key representing the consumer. - * @param {Array} splitNames - An array of the split names we wan't to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatments} Treatments promise which will resolve to the treatments object. - */ - getTreatments(key: SplitKey, splitNames: string[], attributes?: Attributes): AsyncTreatments, - /** - * Returns a Treatments value, whick will be (or eventually be) an object with all the maps of treatment and config string for the given features. - * For usage on NodeJS as we don't have only one key. - * @function getTreatmentsWithConfig - * @param {string} key - The string key representing the consumer. - * @param {Array} splitNames - An array of the split names we wan't to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatmentsWithConfig} TreatmentsWithConfig promise which will resolve to the map of TreatmentsWithConfig objects. - */ - getTreatmentsWithConfig(key: SplitKey, splitNames: string[], attributes?: Attributes): AsyncTreatmentsWithConfig, - /** - * Tracks an event to be fed to the results product on Split Webconsole and returns a promise to signal when the event was successfully queued (or not). - * @function track - * @param {SplitKey} key - The key that identifies the entity related to this event. - * @param {string} trafficType - The traffic type of the entity related to this event. - * @param {string} eventType - The event type corresponding to this event. - * @param {number=} value - The value of this event. - * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. - * @returns {Promise} A promise that resolves to a boolean indicating if the event was added to the queue succesfully or not. - */ - track(key: SplitIO.SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): Promise - } - /** - * This represents the interface for the Client instance with synchronous storage for client-side SDK, where each client has associated a key and optionally a traffic type. - * @interface IClient - * @extends IBasicClient - */ - export interface ICsClient extends IBasicClient { - /** - * Returns a Treatment value, which will be the treatment string for the given feature. - * @function getTreatment - * @param {string} splitName - The string that represents the split we wan't to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatment} The treatment result. - */ - getTreatment(splitName: string, attributes?: Attributes): Treatment, - /** - * Returns a TreatmentWithConfig value, which will be a map of treatment and the config for that treatment. - * @function getTreatment - * @param {string} splitName - The string that represents the split we wan't to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {TreatmentWithConfig} The treatment or treatment promise which will resolve to the treatment string. - */ - getTreatmentWithConfig(splitName: string, attributes?: Attributes): TreatmentWithConfig, - /** - * Returns a Treatments value, whick will be (or eventually be) an object with the treatments for the given features. - * @function getTreatments - * @param {Array} splitNames - An array of the split names we wan't to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The treatments or treatments promise which will resolve to the treatments object. - */ - getTreatments(splitNames: string[], attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, whick will be an object with the TreatmentWithConfig (a map with both treatment and config string) for the given features. - * @function getTreatmentsWithConfig - * @param {Array} splitNames - An array of the split names we wan't to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {TreatmentsWithConfig} The map with all the TreatmentWithConfig objects - */ - getTreatmentsWithConfig(splitNames: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Tracks an event to be fed to the results product on Split Webconsole. - * @function track - * @param {string} trafficType - The traffic type of the entity related to this event. NOTE: only has to be provided if the client doesn't have a traffic type - * @param {string} eventType - The event type corresponding to this event. - * @param {number=} value - The value of this event. - * @param {Properties=} properties - The properties of this event. Values can be string, number, boolean or null. - * @returns {boolean} Whether the event was added to the queue succesfully or not. - */ - track(...args: [trafficType: string, eventType: string, value?: number, properties?: Properties] | [eventType: string, value?: number, properties?: Properties]): boolean, - /** - * Add an attribute to client's in memory attributes storage - * @function setAttribute - * @param {string} attributeName Attrinute name - * @param {string, number, boolean, list} attributeValue Attribute value - * @returns {boolean} true if the attribute was stored and false otherways - */ - setAttribute(attributeName: string, attributeValue: Object): boolean, - /** - * Returns the attribute with the given key - * @function getAttribute - * @param {string} attributeName Attribute name - * @returns {Object} Attribute with the given key - */ - getAttribute(attributeName: string): Object, - /** - * Add to client's in memory attributes storage the attributes in 'attributes' - * @function setAttributes - * @param {Object} attributes Object with attributes to store - * @returns true if attributes were stored an false otherways - */ - setAttributes(attributes: Record): boolean, - /** - * Return all the attributes stored in client's in memory attributes storage - * @function getAttributes - * @returns {Object} returns all the stored attributes - */ - getAttributes(): Record, - /** - * Removes from client's in memory attributes storage the attribute with the given key - * @function removeAttribute - * @param {string} attributeName - * @returns {boolean} true if attribute was removed and false otherways - */ - removeAttribute(attributeName: string): boolean, - /** - * Remove all the stored attributes in the client's in memory attribute storage - */ - clearAttributes(): boolean - } - /** - * Representation of a manager instance with synchronous storage of the SDK. - * @interface IManager - * @extends IStatusInterface - */ - export interface IManager extends IStatusInterface { - /** - * Get the array of Split names. - * @function names - * @returns {SplitNames} The lists of Split names. - */ - names(): SplitNames; - /** - * Get the array of splits data in SplitView format. - * @function splits - * @returns {SplitViews} The list of SplitIO.SplitView. - */ - splits(): SplitViews; - /** - * Get the data of a split in SplitView format. - * @function split - * @param {string} splitName The name of the split we wan't to get info of. - * @returns {SplitView} The SplitIO.SplitView of the given split. - */ - split(splitName: string): SplitView; - } - /** - * Representation of a manager instance with asynchronous storage of the SDK. - * @interface IAsyncManager - * @extends IStatusInterface - */ - export interface IAsyncManager extends IStatusInterface { - /** - * Get the array of Split names. - * @function names - * @returns {SplitNamesAsync} A promise that will resolve to the array of Splitio.SplitNames. - */ - names(): SplitNamesAsync; - /** - * Get the array of splits data in SplitView format. - * @function splits - * @returns {SplitViewsAsync} A promise that will resolve to the SplitIO.SplitView list. - */ - splits(): SplitViewsAsync; - /** - * Get the data of a split in SplitView format. - * @function split - * @param {string} splitName The name of the split we wan't to get info of. - * @returns {SplitViewAsync} A promise that will resolve to the SplitIO.SplitView value. - */ - split(splitName: string): SplitViewAsync; - } -} diff --git a/src/utils/constants/index.ts b/src/utils/constants/index.ts index 4925e71a..297051a2 100644 --- a/src/utils/constants/index.ts +++ b/src/utils/constants/index.ts @@ -1,4 +1,4 @@ -import { StorageType } from '../../storages/types'; +import { StorageType } from '../../types'; import { SDKMode } from '../../types'; // Special treatments diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index cef0fa0f..0d5733b7 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,5 +1,5 @@ import { ERROR_NULL, ERROR_EMPTY, ERROR_INVALID, WARN_API_KEY, LOG_PREFIX_INSTANTIATION } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { isString } from '../lang'; const item = 'api_key'; diff --git a/src/utils/inputValidation/attribute.ts b/src/utils/inputValidation/attribute.ts index e30d9473..2b1cb664 100644 --- a/src/utils/inputValidation/attribute.ts +++ b/src/utils/inputValidation/attribute.ts @@ -1,5 +1,5 @@ import { isString, isFiniteNumber, isBoolean } from '../../utils/lang'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; export function validateAttribute(log: ILogger, attributeKey: string, attributeValue: Object, method: string): boolean { if (!isString(attributeKey) || attributeKey.length === 0) { diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index e9824113..5ff64283 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -1,10 +1,10 @@ import { isObject } from '../lang'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { Attributes } from '../../types'; +import { ILogger } from '../../types'; import { validateAttribute } from './attribute'; import { ERROR_NOT_PLAIN_OBJECT } from '../../logger/constants'; -export function validateAttributes(log: ILogger, maybeAttrs: any, method: string): SplitIO.Attributes | undefined | false { +export function validateAttributes(log: ILogger, maybeAttrs: any, method: string): Attributes | undefined | false { // Attributes are optional if (maybeAttrs == undefined || isObject(maybeAttrs)) // eslint-disable-line eqeqeq return maybeAttrs; diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index 98311224..2b841b84 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -1,5 +1,5 @@ import { ERROR_EVENT_TYPE_FORMAT, ERROR_NULL, ERROR_INVALID, ERROR_EMPTY } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { isString } from '../lang'; const EVENT_TYPE_REGEX = /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/; diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index 1fb2984e..2661dde5 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -1,7 +1,7 @@ import { isObject, isString, isFiniteNumber, isBoolean } from '../lang'; import { objectAssign } from '../lang/objectAssign'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { Properties } from '../../types'; +import { ILogger } from '../../types'; import { ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES } from '../../logger/constants'; const ECMA_SIZES = { @@ -14,7 +14,7 @@ const MAX_PROPERTIES_AMOUNT = 300; const MAX_EVENT_SIZE = 1024 * 32; const BASE_EVENT_SIZE = 1024; // We assume 1kb events without properties (avg measured) -export function validateEventProperties(log: ILogger, maybeProperties: any, method: string): { properties: SplitIO.Properties | null | false, size: number } { +export function validateEventProperties(log: ILogger, maybeProperties: any, method: string): { properties: Properties | null | false, size: number } { if (maybeProperties == undefined) return { properties: null, size: BASE_EVENT_SIZE }; // eslint-disable-line eqeqeq if (!isObject(maybeProperties)) { diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index 9b7bdd16..a7b98a0c 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -1,5 +1,5 @@ import { ERROR_NOT_FINITE } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { isFiniteNumber } from '../lang'; export function validateEventValue(log: ILogger, maybeValue: any, method: string): number | false { diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 05ad0aad..3d9e2a43 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,5 +1,5 @@ import { ERROR_CLIENT_DESTROYED, CLIENT_NOT_READY } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { IReadinessManager } from '../../readiness/types'; export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager, method: string): boolean { diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index 9068bed6..65e1ec06 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -1,6 +1,6 @@ import { isObject, isString, isFiniteNumber, toString } from '../lang'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { SplitKey } from '../../types'; +import { ILogger } from '../../types'; import { ERROR_NULL, WARN_CONVERTING, ERROR_EMPTY, ERROR_TOO_LONG, ERROR_INVALID, ERROR_INVALID_KEY_OBJECT } from '../../logger/constants'; const KEY_MAX_LENGTH = 250; @@ -33,7 +33,7 @@ function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: str return false; } -export function validateKey(log: ILogger, maybeKey: any, method: string): SplitIO.SplitKey | false { +export function validateKey(log: ILogger, maybeKey: any, method: string): SplitKey | false { if (isObject(maybeKey)) { // Validate key object const matchingKey = validateKeyValue(log, maybeKey.matchingKey, method, 'matchingKey'); diff --git a/src/utils/inputValidation/preloadedData.ts b/src/utils/inputValidation/preloadedData.ts index 0b02c6c2..65570f18 100644 --- a/src/utils/inputValidation/preloadedData.ts +++ b/src/utils/inputValidation/preloadedData.ts @@ -1,7 +1,7 @@ import { isObject, isString, isFiniteNumber } from '../lang'; import { validateSplit } from './split'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; +import { PreloadedData } from '../../storages/types'; function validateTimestampData(log: ILogger, maybeTimestamp: any, method: string, item: string) { if (isFiniteNumber(maybeTimestamp) && maybeTimestamp > -1) return true; @@ -42,7 +42,7 @@ function validateSegmentsData(log: ILogger, maybeSegmentsData: any, method: stri return false; } -export function validatePreloadedData(log: ILogger, maybePreloadedData: any, method: string): maybePreloadedData is SplitIO.PreloadedData { +export function validatePreloadedData(log: ILogger, maybePreloadedData: any, method: string): maybePreloadedData is PreloadedData { if (!isObject(maybePreloadedData)) { log.error(`${method}: preloadedData must be an object.`); } else if ( diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index b7261604..ea13f59f 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -1,5 +1,5 @@ import { ERROR_NULL, ERROR_INVALID, WARN_TRIMMING, ERROR_EMPTY } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { isString } from '../lang'; // include BOM and nbsp diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index ddafa767..f9b1cb46 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -1,6 +1,6 @@ import { SPLIT_NOT_FOUND } from '../labels'; import { IReadinessManager } from '../../readiness/types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { WARN_NOT_EXISTENT_SPLIT } from '../../logger/constants'; /** diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index ee381210..ed09ca43 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -1,5 +1,5 @@ import { ERROR_EMPTY_ARRAY } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { uniq } from '../lang'; import { validateSplit } from './split'; diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index 01c64dbd..e458b2ce 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -1,5 +1,5 @@ import { ERROR_NULL, ERROR_INVALID, ERROR_EMPTY, WARN_LOWERCASE_TRAFFIC_TYPE } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { isString } from '../lang'; const CAPITAL_LETTERS_REGEX = /[A-Z]/; diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index 743ceb8f..43187635 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -4,7 +4,7 @@ import { ISplitsCacheBase } from '../../storages/types'; import { IReadinessManager } from '../../readiness/types'; import { SDKMode } from '../../types'; import { MaybeThenable } from '../../dtos/types'; -import { ILogger } from '../../logger/types'; +import { ILogger } from '../../types'; import { WARN_NOT_EXISTENT_TT } from '../../logger/constants'; function logTTExistanceWarning(log: ILogger, maybeTT: string, method: string) { diff --git a/src/utils/key/index.ts b/src/utils/key/index.ts index aa252beb..c8be0988 100644 --- a/src/utils/key/index.ts +++ b/src/utils/key/index.ts @@ -1,29 +1,29 @@ -import { SplitIO } from '../../types'; +import { SplitKey, SplitKeyObject } from '../../types'; import { isObject } from '../lang'; -// function isSplitKeyObject(key: any): key is SplitIO.SplitKeyObject { +// function isSplitKeyObject(key: any): key is SplitKeyObject { // return key !== undefined && key !== null && typeof key.matchingKey === 'string'; // } // returns the matchingKey if the Key is defined as an object or the key itself if it is a string -export function getMatching(key: SplitIO.SplitKey): string { - return isObject(key) ? (key as SplitIO.SplitKeyObject).matchingKey : key as string; +export function getMatching(key?: SplitKey): string { + return isObject(key) ? (key as SplitKeyObject).matchingKey : key as string; } // if the key is a string, there's no bucketingKey (undefined) -export function getBucketing(key: SplitIO.SplitKey): string | undefined { - return isObject(key) ? (key as SplitIO.SplitKeyObject).bucketingKey : undefined; +export function getBucketing(key: SplitKey): string | undefined { + return isObject(key) ? (key as SplitKeyObject).bucketingKey : undefined; } /** * Verify type of key and return a valid object key used for get treatment for a * specific split. */ -export function keyParser(key: SplitIO.SplitKey): SplitIO.SplitKeyObject { +export function keyParser(key: SplitKey): SplitKeyObject { if (isObject(key)) { return { - matchingKey: (key as SplitIO.SplitKeyObject).matchingKey, - bucketingKey: (key as SplitIO.SplitKeyObject).bucketingKey + matchingKey: (key as SplitKeyObject).matchingKey, + bucketingKey: (key as SplitKeyObject).bucketingKey }; } else { return { diff --git a/src/utils/settingsValidation/consent.ts b/src/utils/settingsValidation/consent.ts index 98b4112b..6a7e477e 100644 --- a/src/utils/settingsValidation/consent.ts +++ b/src/utils/settingsValidation/consent.ts @@ -1,6 +1,5 @@ import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; -import { ConsentStatus } from '../../types'; +import { ConsentStatus, ILogger } from '../../types'; import { CONSENT_DECLINED, CONSENT_GRANTED, CONSENT_UNKNOWN } from '../constants'; import { stringToUpperCase } from '../lang'; diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index 9fdc3e09..60b0b55e 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -1,10 +1,10 @@ import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants'; -import { ILogger } from '../../logger/types'; -import { SplitIO } from '../../types'; +import { ILogger } from '../../types'; +import { ImpressionsMode } from '../../types'; import { DEBUG, OPTIMIZED } from '../constants'; import { stringToUpperCase } from '../lang'; -export function validImpressionsMode(log: ILogger, impressionsMode: any): SplitIO.ImpressionsMode { +export function validImpressionsMode(log: ILogger, impressionsMode: any): ImpressionsMode { impressionsMode = stringToUpperCase(impressionsMode); if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) > -1) return impressionsMode; diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index 5ead4509..1c9e9c73 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -1,5 +1,5 @@ import { WARN_INTEGRATION_INVALID } from '../../../logger/constants'; -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; /** * This function validates `settings.integrations` object diff --git a/src/utils/settingsValidation/integrations/configurable.ts b/src/utils/settingsValidation/integrations/configurable.ts index fb24e35b..be06d402 100644 --- a/src/utils/settingsValidation/integrations/configurable.ts +++ b/src/utils/settingsValidation/integrations/configurable.ts @@ -1,6 +1,6 @@ import { validateIntegrations } from './common'; import { isString } from '../../lang'; -import { ILogger } from '../../../logger/types'; +import { ILogger } from '../../../types'; /** * This function validates `settings.integrations` object that consists of a list of configuration items, used by the isomorphic JS SDK. diff --git a/src/utils/settingsValidation/integrations/pluggable.ts b/src/utils/settingsValidation/integrations/pluggable.ts index b4a96ee9..a3abcdca 100644 --- a/src/utils/settingsValidation/integrations/pluggable.ts +++ b/src/utils/settingsValidation/integrations/pluggable.ts @@ -1,6 +1,5 @@ -import { ISettings } from '../../../types'; +import { ISettings, ILogger } from '../../../types'; import { validateIntegrations } from './common'; -import { ILogger } from '../../../logger/types'; /** * This function validates `settings.integrations` object that consists of a list of pluggable integration factories. diff --git a/src/utils/settingsValidation/localhost/builtin.ts b/src/utils/settingsValidation/localhost/builtin.ts index 35a30145..925f61c7 100644 --- a/src/utils/settingsValidation/localhost/builtin.ts +++ b/src/utils/settingsValidation/localhost/builtin.ts @@ -1,5 +1,4 @@ -import { ILogger } from '../../../logger/types'; -import { SDKMode, } from '../../../types'; +import { SDKMode, ILogger } from '../../../types'; import { LocalhostFromObject } from '../../../sync/offline/LocalhostFromObject'; import { validateLocalhost } from './pluggable'; diff --git a/src/utils/settingsValidation/localhost/pluggable.ts b/src/utils/settingsValidation/localhost/pluggable.ts index 3231e612..6455fd86 100644 --- a/src/utils/settingsValidation/localhost/pluggable.ts +++ b/src/utils/settingsValidation/localhost/pluggable.ts @@ -1,6 +1,5 @@ import { ERROR_LOCALHOST_MODULE_REQUIRED } from '../../../logger/constants'; -import { ILogger } from '../../../logger/types'; -import { SDKMode, } from '../../../types'; +import { SDKMode, ILogger } from '../../../types'; import { LOCALHOST_MODE } from '../../constants'; /** diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index 5db9cfb0..cd5d18d2 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -1,11 +1,10 @@ import { isLogLevelString, Logger, LogLevels } from '../../../logger'; -import { ILogger } from '../../../logger/types'; import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; import { isNode } from '../../env/isNode'; import { codesDebug } from '../../../logger/messages/debug'; import { _Map } from '../../lang/maps'; import { getLogLevel } from './commons'; -import { LogLevel } from '../../../types'; +import { LogLevel, ILogger } from '../../../types'; const allCodes = new _Map(codesDebug); diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 7b149990..8e548523 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -1,6 +1,5 @@ import { Logger, LogLevels } from '../../../logger'; -import { ILogger } from '../../../logger/types'; -import { LogLevel } from '../../../types'; +import { LogLevel, ILogger } from '../../../types'; import { getLogLevel } from './commons'; function isLogger(log: any): log is ILogger { diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index eb7b0371..07aa2a72 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -1,20 +1,18 @@ import { STANDALONE_MODE } from '../constants'; import { validateSplits } from '../inputValidation/splits'; -import { ISplitFiltersValidation } from '../../dtos/types'; -import { SplitIO } from '../../types'; -import { ILogger } from '../../logger/types'; +import { ISplitFiltersValidation, SplitFilterType, ILogger } from '../../types'; import { WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_EMPTY, WARN_SPLITS_FILTER_INVALID, SETTINGS_SPLITS_FILTER, LOG_PREFIX_SETTINGS } from '../../logger/constants'; // Split filters metadata. // Ordered according to their precedency when forming the filter query string: `&names=&prefixes=` const FILTERS_METADATA = [ { - type: 'byName' as SplitIO.SplitFilterType, + type: 'byName' as SplitFilterType, maxLength: 400, queryParam: 'names=' }, { - type: 'byPrefix' as SplitIO.SplitFilterType, + type: 'byPrefix' as SplitFilterType, maxLength: 50, queryParam: 'prefixes=' } @@ -23,7 +21,7 @@ const FILTERS_METADATA = [ /** * Validates that the given value is a valid filter type */ -function validateFilterType(maybeFilterType: any): maybeFilterType is SplitIO.SplitFilterType { +function validateFilterType(maybeFilterType: any): maybeFilterType is SplitFilterType { return FILTERS_METADATA.some(filterMetadata => filterMetadata.type === maybeFilterType); } @@ -37,7 +35,7 @@ function validateFilterType(maybeFilterType: any): maybeFilterType is SplitIO.Sp * * @throws Error if the sanitized list exceeds the length indicated by `maxLength` */ -function validateSplitFilter(log: ILogger, type: SplitIO.SplitFilterType, values: string[], maxLength: number) { +function validateSplitFilter(log: ILogger, type: SplitFilterType, values: string[], maxLength: number) { // validate and remove invalid and duplicated values let result = validateSplits(log, values, LOG_PREFIX_SETTINGS, `${type} filter`, `${type} filter value`); @@ -63,7 +61,7 @@ function validateSplitFilter(log: ILogger, type: SplitIO.SplitFilterType, values * @param {Object} groupedFilters object of filters. Each filter must be a list of valid, unique and ordered string values. * @returns null or string with the `split filter query` component of the URL. */ -function queryStringBuilder(groupedFilters: Record) { +function queryStringBuilder(groupedFilters: Record) { const queryParams: string[] = []; FILTERS_METADATA.forEach(({ type, queryParam }) => { const filter = groupedFilters[type]; @@ -109,7 +107,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: // Validate filters and group their values by filter type inside `groupedFilters` object res.validFilters = maybeSplitFilters.filter((filter, index) => { if (filter && validateFilterType(filter.type) && Array.isArray(filter.values)) { - res.groupedFilters[filter.type as SplitIO.SplitFilterType] = res.groupedFilters[filter.type as SplitIO.SplitFilterType].concat(filter.values); + res.groupedFilters[filter.type as SplitFilterType] = res.groupedFilters[filter.type as SplitFilterType].concat(filter.values); return true; } else { log.warn(WARN_SPLITS_FILTER_INVALID, [index]); diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index 097ce95d..6bf8dace 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -1,6 +1,5 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; -import { ISettings, SDKMode } from '../../../types'; -import { ILogger } from '../../../logger/types'; +import { ISettings, SDKMode, ILogger } from '../../../types'; import { ERROR_STORAGE_INVALID } from '../../../logger/constants'; import { LOCALHOST_MODE, STANDALONE_MODE, STORAGE_PLUGGABLE, STORAGE_LOCALSTORAGE, STORAGE_MEMORY } from '../../../utils/constants'; import { IStorageFactoryParams, IStorageSync } from '../../../storages/types';