Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0e67f8a
implementation and unit tests
EmilianoSanchez Feb 23, 2022
5862079
updated settings interface
EmilianoSanchez Feb 23, 2022
b2dfd2e
update submitters to not drop data if queues are full but consent has…
EmilianoSanchez Feb 23, 2022
7342389
Modify browser listener flow to avoid flushing data without consent
EmilianoSanchez Feb 23, 2022
bae3e5e
added getter & setter for user consent in factory
EmilianoSanchez Feb 24, 2022
961f56c
constants to uppercase
EmilianoSanchez Feb 24, 2022
8d1714c
Merge pull request #81 from splitio/user_consent_handle_trackers_and_…
EmilianoSanchez Feb 24, 2022
81e7031
Merge branch 'user_consent_handle_trackers_and_submitters' into user_…
EmilianoSanchez Feb 24, 2022
37cc9fb
constants to uppercase
EmilianoSanchez Feb 24, 2022
86448b5
Merge pull request #82 from splitio/user_consent_browser_listener
EmilianoSanchez Feb 24, 2022
e978c07
Merge branch 'user_consent_baseline' into user_consent_setter_and_getter
EmilianoSanchez Feb 24, 2022
9669ad8
constants to uppercase
EmilianoSanchez Feb 24, 2022
fb7f3f0
validate config.userConsent
EmilianoSanchez Feb 24, 2022
14105d8
fixed type check issue
EmilianoSanchez Feb 24, 2022
881e534
Merge branch 'user_consent_setter_and_getter' into user_consent_confi…
EmilianoSanchez Feb 24, 2022
9e71ee2
fixed test
EmilianoSanchez Feb 24, 2022
3dc3638
localstorage update
EmilianoSanchez Feb 25, 2022
d855259
Merge pull request #85 from splitio/change/localstorageKeyChanges
EmilianoSanchez Feb 25, 2022
692d032
Merge branch 'user_consent_baseline' into user_consent_setter_and_getter
EmilianoSanchez Mar 2, 2022
cb95986
Merge branch 'user_consent_setter_and_getter' into user_consent_confi…
EmilianoSanchez Mar 2, 2022
a16b603
prepare rc
EmilianoSanchez Mar 2, 2022
a4bf0fa
update validatePrefix function, for consistency with JS SDK
EmilianoSanchez Mar 3, 2022
0e36a90
feedback and polishing
EmilianoSanchez Mar 3, 2022
57d2191
Merge pull request #84 from splitio/user_consent_config_validation
EmilianoSanchez Mar 3, 2022
582b53a
Merge pull request #83 from splitio/user_consent_setter_and_getter
EmilianoSanchez Mar 3, 2022
002912f
fixed issue with event submitter push window
EmilianoSanchez Mar 4, 2022
8255eae
validate undefined authorizationKey in SSEClient
EmilianoSanchez Mar 8, 2022
9ab79d2
move consent check from client to trackers
EmilianoSanchez Mar 8, 2022
ac554e2
Merge pull request #87 from splitio/user_consent_polishing
EmilianoSanchez Mar 8, 2022
6bff120
fixed map, to use ponyfill on browsers with partial support of Map co…
EmilianoSanchez Mar 9, 2022
bbaed1f
updated isClientSide flag
EmilianoSanchez Mar 14, 2022
6eb52fc
code syntax refactor
EmilianoSanchez Mar 15, 2022
7620e08
in-transit encryption support added
EmilianoSanchez Mar 15, 2022
20cb703
Merge pull request #88 from splitio/user_consent_trackers_refactor
EmilianoSanchez Mar 15, 2022
05637d0
forwarding connectionTimeout to ioredis connectTimeout
EmilianoSanchez Mar 17, 2022
ff721fd
Merge pull request #89 from splitio/redis_intransit_encryption_support
EmilianoSanchez Mar 25, 2022
e1e6698
implementation and tests
EmilianoSanchez Mar 25, 2022
c5aee70
fixed type issue
EmilianoSanchez Mar 25, 2022
4621c01
updated isObject util function
EmilianoSanchez Mar 28, 2022
94173b5
Merge pull request #91 from splitio/isobject_util_update
mmelograno Mar 28, 2022
cb32d4e
performance improvement
EmilianoSanchez Mar 29, 2022
b9161b2
size improvement
EmilianoSanchez Mar 29, 2022
5bcf761
updated some type signatures
EmilianoSanchez Mar 29, 2022
4242996
Merge pull request #93 from splitio/isobject_util_update
EmilianoSanchez Mar 29, 2022
5fa4af7
Merge branch 'user_consent_baseline' into settings_key_and_tt_validation
EmilianoSanchez Mar 29, 2022
5020990
handle key and TT validation separately
EmilianoSanchez Mar 29, 2022
0ca9ff5
fixed issue with a info log
EmilianoSanchez Mar 31, 2022
f053eaf
added info log for initial user consent
EmilianoSanchez Mar 31, 2022
dd08b91
Merge pull request #90 from splitio/settings_key_and_tt_validation
EmilianoSanchez Mar 31, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@splitsoftware/splitio-commons",
"version": "1.2.1-rc.3",
"version": "1.2.1-rc.11",
"description": "Split Javascript SDK common components",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand Down
2 changes: 1 addition & 1 deletion src/evaluator/parser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, splitEvaluator: ISplitEvaluator) => {
return (key: string, attributes: SplitIO.Attributes | undefined, splitEvaluator: ISplitEvaluator) => {
const value = sanitizeValue(log, key, matcherDto, attributes);
const result = value !== undefined && matcher ? matcher(value, splitEvaluator) : false;

Expand Down
4 changes: 2 additions & 2 deletions src/evaluator/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ILogger } from '../logger/types';

export interface IDependencyMatcherValue {
key: SplitIO.SplitKey,
attributes: SplitIO.Attributes
attributes?: SplitIO.Attributes
}

export interface IMatcherDto {
Expand All @@ -27,7 +27,7 @@ export interface IEvaluation {

export type IEvaluationResult = IEvaluation & { treatment: string }

export type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes, storage: IStorageSync | IStorageAsync) => MaybeThenable<IEvaluation>
export type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync) => MaybeThenable<IEvaluation>

export type IEvaluator = (key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable<IEvaluation | undefined>

Expand Down
4 changes: 2 additions & 2 deletions src/evaluator/value/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ILogger } from '../../logger/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?: SplitIO.Attributes) {
let value = undefined;
if (attributeName) {
if (attributes) {
Expand All @@ -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?: SplitIO.Attributes) {
const attributeName = matcherDto.attribute;
const valueToMatch = parseValue(log, key, attributeName, attributes);
const sanitizedValue = sanitize(log, matcherDto.type, valueToMatch, matcherDto.dataType, attributes);
Expand Down
4 changes: 2 additions & 2 deletions src/evaluator/value/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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?: SplitIO.Attributes): IDependencyMatcherValue {
return {
key: sanitizedValue,
attributes
Expand Down Expand Up @@ -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<string | number> | undefined, dataType: string, attributes: SplitIO.Attributes) {
export function sanitize(log: ILogger, matcherTypeID: number, value: string | number | boolean | Array<string | number> | undefined, dataType: string, attributes?: SplitIO.Attributes) {
const processor = getProcessingFunction(matcherTypeID, dataType);
let sanitizedValue: string | number | boolean | Array<string | number> | IDependencyMatcherValue | undefined;

Expand Down
4 changes: 2 additions & 2 deletions src/integrations/pluggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ export function pluggableIntegrationsManagerFactory(

// Exception safe methods: each integration module is responsable for handling errors
return {
handleImpression: function (impressionData: SplitIO.ImpressionData) {
handleImpression(impressionData: SplitIO.ImpressionData) {
listeners.forEach(listener => listener.queue({ type: SPLIT_IMPRESSION, payload: impressionData }));
},
handleEvent: function (eventData: SplitIO.EventData) {
handleEvent(eventData: SplitIO.EventData) {
listeners.forEach(listener => listener.queue({ type: SPLIT_EVENT, payload: eventData }));
}
};
Expand Down
36 changes: 34 additions & 2 deletions src/listeners/__tests__/browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@ beforeAll(() => {
});
});

// clean mocks
afterEach(() => {
// clear mocks
beforeEach(() => {
(global.window.addEventListener as jest.Mock).mockClear();
(global.window.removeEventListener as jest.Mock).mockClear();
if (global.window.navigator.sendBeacon) (global.window.navigator.sendBeacon as jest.Mock).mockClear();
Object.values(fakeSplitApi).forEach(method => method.mockClear());
});

// delete mocks from global
Expand Down Expand Up @@ -227,3 +228,34 @@ test('Browser JS listener / standalone mode / Impressions debug mode without sen
// restore sendBeacon API
global.navigator.sendBeacon = sendBeacon;
});

test('Browser JS listener / standalone mode / user consent status', () => {
const syncManagerMock = {};
const settings = { ...fullSettings };

// @ts-expect-error
const listener = new BrowserSignalListener(syncManagerMock, settings, fakeStorageOptimized as IStorageSync, fakeSplitApi);

listener.start();

settings.userConsent = 'UNKNOWN';
triggerUnloadEvent();
settings.userConsent = 'DECLINED';
triggerUnloadEvent();

// Unload event was triggered when user consent was unknown and declined. Thus sendBeacon and post services should not be called
expect(global.window.navigator.sendBeacon).toBeCalledTimes(0);
expect(fakeSplitApi.postTestImpressionsBulk).not.toBeCalled();
expect(fakeSplitApi.postEventsBulk).not.toBeCalled();
expect(fakeSplitApi.postTestImpressionsCount).not.toBeCalled();

settings.userConsent = 'GRANTED';
triggerUnloadEvent();
settings.userConsent = undefined;
triggerUnloadEvent();

// Unload event was triggered when user consent was granted and undefined. Thus sendBeacon should be called 6 times (3 times per event in optimized mode).
expect(global.window.navigator.sendBeacon).toBeCalledTimes(6);

listener.stop();
});
22 changes: 13 additions & 9 deletions src/listeners/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { OPTIMIZED, DEBUG } from '../utils/constants';
import { objectAssign } from '../utils/lang/objectAssign';
import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
import { ISyncManager } from '../sync/types';
import { isConsentGranted } from '../utils/consent';

// 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring.
const UNLOAD_DOM_EVENT = 'unload';
Expand Down Expand Up @@ -65,15 +66,18 @@ export class BrowserSignalListener implements ISignalListener {
flushData() {
if (!this.syncManager) return; // In consumer mode there is not sync manager and data to flush

const eventsUrl = this.settings.urls.events;
const extraMetadata = {
// sim stands for Sync/Split Impressions Mode
sim: this.settings.sync.impressionsMode === OPTIMIZED ? OPTIMIZED : DEBUG
};
// Flush data if there is user consent
if (isConsentGranted(this.settings)) {
const eventsUrl = this.settings.urls.events;
const extraMetadata = {
// sim stands for Sync/Split Impressions Mode
sim: this.settings.sync.impressionsMode === OPTIMIZED ? OPTIMIZED : DEBUG
};

this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
this._flushData(eventsUrl + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
if (this.storage.impressionCounts) this._flushData(eventsUrl + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, fromImpressionCountsCollector);
this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
this._flushData(eventsUrl + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
if (this.storage.impressionCounts) this._flushData(eventsUrl + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, fromImpressionCountsCollector);
}

// Close streaming connection
if (this.syncManager.pushManager) this.syncManager.pushManager.stop();
Expand All @@ -84,7 +88,7 @@ export class BrowserSignalListener implements ISignalListener {
if (!cache.isEmpty()) {
const dataPayload = fromCacheToPayload ? fromCacheToPayload(cache.state()) : cache.state();
if (!this._sendBeacon(url, dataPayload, extraMetadata)) {
postService(JSON.stringify(dataPayload)).catch(() => { }); // no-op just to catch a possible exceptions
postService(JSON.stringify(dataPayload)).catch(() => { }); // no-op just to catch a possible exception
}
cache.clear();
}
Expand Down
6 changes: 5 additions & 1 deletion src/logger/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export const SYNC_CONTINUE_POLLING = 118;
export const SYNC_STOP_POLLING = 119;
export const EVENTS_TRACKER_SUCCESS = 120;
export const IMPRESSIONS_TRACKER_SUCCESS = 121;
export const USER_CONSENT_UPDATED = 122;
export const USER_CONSENT_NOT_UPDATED = 123;
export const USER_CONSENT_INITIAL = 124;

export const ENGINE_VALUE_INVALID = 200;
export const ENGINE_VALUE_NO_ATTRIBUTES = 201;
Expand Down Expand Up @@ -115,10 +118,11 @@ export const ERROR_INVALID_KEY_OBJECT = 317;
export const ERROR_INVALID = 318;
export const ERROR_EMPTY = 319;
export const ERROR_EMPTY_ARRAY = 320;
export const ERROR_INVALID_IMPRESSIONS_MODE = 321;
export const ERROR_INVALID_CONFIG_PARAM = 321;
export const ERROR_HTTP = 322;
export const ERROR_LOCALHOST_MODULE_REQUIRED = 323;
export const ERROR_STORAGE_INVALID = 324;
export const ERROR_NOT_BOOLEAN = 325;

// Log prefixes (a.k.a. tags or categories)
export const LOG_PREFIX_SETTINGS = 'settings';
Expand Down
6 changes: 3 additions & 3 deletions src/logger/messages/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export const codesDebug: [number, string][] = codesInfo.concat([
// SDK
[c.CLEANUP_REGISTERING, c.LOG_PREFIX_CLEANUP + 'Registering cleanup handler %s'],
[c.CLEANUP_DEREGISTERING, c.LOG_PREFIX_CLEANUP + 'Deregistering cleanup handler %s'],
[c.RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'],
[c.RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'],
[c.RETRIEVE_MANAGER, ' Retrieving manager instance.'],
[c.RETRIEVE_CLIENT_DEFAULT, 'Retrieving default SDK client.'],
[c.RETRIEVE_CLIENT_EXISTING, 'Retrieving existing SDK client.'],
[c.RETRIEVE_MANAGER, 'Retrieving manager instance.'],
// synchronizer
[c.SYNC_OFFLINE_DATA, c.LOG_PREFIX_SYNC_OFFLINE + 'Splits data: \n%s'],
[c.SYNC_SPLITS_FETCH, c.LOG_PREFIX_SYNC_SPLITS + 'Spin up split update using since = %s'],
Expand Down
5 changes: 3 additions & 2 deletions src/logger/messages/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const codesError: [number, string][] = [
[c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid Split, no valid rules found'],
// SDK
[c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'],
[c.ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'],
[c.ERROR_CLIENT_CANNOT_GET_READY, 'The SDK will not get ready. Reason: %s'],
[c.ERROR_IMPRESSIONS_TRACKER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Could not store impressions bulk with %s impression(s). Error: %s'],
[c.ERROR_IMPRESSIONS_LISTENER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Impression listener logImpression method threw: %s.'],
[c.ERROR_EVENTS_TRACKER, c.LOG_PREFIX_EVENTS_TRACKER + 'Failed to queue %s'],
Expand All @@ -28,8 +28,9 @@ export const codesError: [number, string][] = [
[c.ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'],
[c.ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'],
[c.ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'],
[c.ERROR_NOT_BOOLEAN, '%s: provided param must be a boolean value.'],
// initialization / settings validation
[c.ERROR_INVALID_IMPRESSIONS_MODE, c.LOG_PREFIX_SETTINGS + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'],
[c.ERROR_INVALID_CONFIG_PARAM, c.LOG_PREFIX_SETTINGS + ': you passed an invalid "%s" config param. It should be one of the following values: %s. Defaulting to "%s".'],
[c.ERROR_LOCALHOST_MODULE_REQUIRED, c.LOG_PREFIX_SETTINGS + ': an invalid value was received for "sync.localhostMode" config. A valid entity should be provided for localhost mode.'],
[c.ERROR_STORAGE_INVALID, c.LOG_PREFIX_SETTINGS+': The provided storage is invalid.%s Fallbacking into default MEMORY storage'],
];
7 changes: 5 additions & 2 deletions src/logger/messages/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ export const codesInfo: [number, string][] = codesWarn.concat([
// SDK
[c.IMPRESSION, c.LOG_PREFIX_IMPRESSIONS_TRACKER +'Split: %s. Key: %s. Evaluation: %s. Label: %s'],
[c.IMPRESSION_QUEUEING, c.LOG_PREFIX_IMPRESSIONS_TRACKER +'Queueing corresponding impression.'],
[c.NEW_SHARED_CLIENT, ' New shared client instance created.'],
[c.NEW_FACTORY, ' New Split SDK instance created.'],
[c.NEW_SHARED_CLIENT, 'New shared client instance created.'],
[c.NEW_FACTORY, 'New Split SDK instance created.'],
[c.EVENTS_TRACKER_SUCCESS, c.LOG_PREFIX_EVENTS_TRACKER + 'Successfully queued %s'],
[c.IMPRESSIONS_TRACKER_SUCCESS, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Successfully stored %s impression(s).'],
[c.USER_CONSENT_UPDATED, 'setUserConsent: consent status changed from %s to %s.'],
[c.USER_CONSENT_NOT_UPDATED, 'setUserConsent: call had no effect because it was the current consent status (%s).'],
[c.USER_CONSENT_INITIAL, 'Starting the SDK with %s user consent. No data will be sent.'],

// synchronizer
[c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
Expand Down
29 changes: 0 additions & 29 deletions src/sdkClient/__tests__/sdkClientMethodCS.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { sdkClientMethodCSFactory as sdkClientMethodCSWithTTFactory } from '../s
import { sdkClientMethodCSFactory } from '../sdkClientMethodCS';
import { assertClientApi } from './testUtils';

/** Mocks */
import * as clientCS from '../clientCS';
const clientCSDecoratorSpy = jest.spyOn(clientCS, 'clientCSDecorator');

import { settingsWithKey, settingsWithKeyAndTT, settingsWithKeyObject } from '../../utils/settingsValidation/__tests__/settings.mocks';

const partialStorages: { destroy: jest.Mock }[] = [];
Expand Down Expand Up @@ -220,31 +216,6 @@ describe('sdkClientMethodCSFactory', () => {
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)('invalid key/TT binds a false key/TT in the default client', (sdkClientMethodCSFactory, ignoresTT) => {
const paramsWithInvalidKeyAndTT = {
...params,
settings: {
...params.settings,
core: {
key: true, // invalid key
trafficType: '' // invalid TT
}
}
};

(clientCSDecoratorSpy as jest.Mock).mockClear();
// @ts-expect-error
const sdkClientMethod = sdkClientMethodCSFactory(paramsWithInvalidKeyAndTT);

// calling the function should return a client instance
const client = sdkClientMethod();
assertClientApi(client, params.sdkReadinessManager.sdkStatus);

// but with false as binded key and TT
if (ignoresTT) expect(clientCSDecoratorSpy).toHaveBeenCalledWith(expect.anything(), expect.anything(), false);
else expect(clientCSDecoratorSpy).toHaveBeenCalledWith(expect.anything(), expect.anything(), false, false);
});

test.each(testTargets)('attributes binding - main client', (sdkClientMethodCSFactory) => {
// @ts-expect-error
const sdkClientMethod = sdkClientMethodCSFactory(params);
Expand Down
5 changes: 3 additions & 2 deletions src/sdkClient/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants';
*/
// @TODO missing time tracking to collect telemetry
export function clientFactory(params: IClientFactoryParams): SplitIO.IClient | SplitIO.IAsyncClient {
const { sdkReadinessManager: { readinessManager }, storage, settings: { log, mode }, impressionsTracker, eventTracker } = params;
const { sdkReadinessManager: { readinessManager }, storage, settings, impressionsTracker, eventTracker } = params;
const { log, mode } = settings;

function getTreatment(key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, withConfig = false) {
const wrapUp = (evaluationResult: IEvaluationResult) => {
Expand Down Expand Up @@ -124,6 +125,6 @@ export function clientFactory(params: IClientFactoryParams): SplitIO.IClient | S
getTreatments,
getTreatmentsWithConfig,
track,
isBrowserClient: false
isClientSide: false
} as SplitIO.IClient | SplitIO.IAsyncClient;
}
2 changes: 1 addition & 1 deletion src/sdkClient/clientCS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ export function clientCSDecorator(log: ILogger, client: SplitIO.IClient, key: Sp
// Key is bound to the `track` method. Same thing happens with trafficType but only if provided
track: trafficType ? clientCS.track.bind(clientCS, key, trafficType) : clientCS.track.bind(clientCS, key),

isBrowserClient: true
isClientSide: true
}) as SplitIO.ICsClient;
}
15 changes: 8 additions & 7 deletions src/sdkClient/clientInputValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ import { startsWith } from '../utils/lang';
import { CONTROL, CONTROL_WITH_CONFIG } from '../utils/constants';
import { IReadinessManager } from '../readiness/types';
import { MaybeThenable } from '../dtos/types';
import { SplitIO } from '../types';
import { ILogger } from '../logger/types';
import { ISettings, SplitIO } from '../types';
import { isStorageSync } from '../trackers/impressionObserver/utils';

/**
* 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<TClient extends SplitIO.IClient | SplitIO.IAsyncClient>(log: ILogger, client: TClient, readinessManager: IReadinessManager, isStorageSync = false): TClient {
export function clientInputValidationDecorator<TClient extends SplitIO.IClient | SplitIO.IAsyncClient>(settings: ISettings, client: TClient, readinessManager: IReadinessManager): TClient {

const log = settings.log;
const isSync = isStorageSync(settings);

/**
* Avoid repeating this validations code
Expand All @@ -47,8 +50,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
}

function wrapResult<T>(value: T): MaybeThenable<T> {
if (isStorageSync) return value;
return Promise.resolve(value);
return isSync ? value : Promise.resolve(value);
}

function getTreatment(maybeKey: SplitIO.SplitKey, maybeSplit: string, maybeAttributes?: SplitIO.Attributes) {
Expand Down Expand Up @@ -108,8 +110,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
if (isOperational && key && tt && event && eventValue !== false && properties !== false) { // @ts-expect-error
return client.track(key, tt, event, eventValue, properties, size);
} else {
if (isStorageSync) return false;
return Promise.resolve(false);
return isSync ? false : Promise.resolve(false);
}
}

Expand Down
Loading