Skip to content

Commit 2950ee6

Browse files
Merge pull request #359 from splitio/breaking_changes_remove_deprecated_features
[Breaking change] Remove SDK clients with bound traffic type
2 parents c7a2002 + 2459b10 commit 2950ee6

File tree

16 files changed

+43
-272
lines changed

16 files changed

+43
-272
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
- Removed `/mySegments` endpoint from SplitAPI module, as it is replaced by `/memberships` endpoint.
88
- Removed support for MY_SEGMENTS_UPDATE and MY_SEGMENTS_UPDATE_V2 notification types, as they are replaced by MEMBERSHIPS_MS_UPDATE and MEMBERSHIPS_LS_UPDATE notification types.
99
- Removed the deprecated `GOOGLE_ANALYTICS_TO_SPLIT` and `SPLIT_TO_GOOGLE_ANALYTICS` integrations.
10+
- Removed the migration logic for the old format of MySegments keys in LocalStorage introduced in JavaScript SDK v10.17.3.
11+
- Removed the `sdkClientMethodCSWithTT` function, which handled the logic to bound an optional traffic type to SDK clients. Client-side SDK implementations must use `sdkClientMethodCS` module, which, unlike the previous function, does not allow passing a traffic type but simplifies the SDK API.
1012
- Removed internal ponyfills for `Map` and `Set` global objects, dropping support for IE and other outdated browsers. The SDK now requires the runtime environment to support these features natively or to provide a polyfill.
1113

1214
1.17.0 (September 6, 2024)

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@splitsoftware/splitio-commons",
3-
"version": "1.17.1-rc.1",
3+
"version": "2.0.0-rc.0",
44
"description": "Split JavaScript SDK common components",
55
"main": "cjs/index.js",
66
"module": "esm/index.js",

src/sdkClient/__tests__/sdkClientMethodCS.spec.ts

Lines changed: 23 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { sdkClientMethodCSFactory as sdkClientMethodCSWithTTFactory } from '../sdkClientMethodCSWithTT';
21
import { sdkClientMethodCSFactory } from '../sdkClientMethodCS';
32
import { assertClientApi } from './testUtils';
43
import { telemetryTrackerFactory } from '../../trackers/telemetryTracker';
5-
import { settingsWithKey, settingsWithKeyAndTT, settingsWithKeyObject } from '../../utils/settingsValidation/__tests__/settings.mocks';
4+
import { settingsWithKey, settingsWithKeyObject } from '../../utils/settingsValidation/__tests__/settings.mocks';
65

76
const partialStorages: { destroy: jest.Mock }[] = [];
87

@@ -75,13 +74,7 @@ describe('sdkClientMethodCSFactory', () => {
7574
params.clients = {};
7675
});
7776

78-
// list of factory functions and their types (whether it ignores TT or not)
79-
const testTargets = [
80-
[sdkClientMethodCSWithTTFactory, false],
81-
[sdkClientMethodCSFactory, true]
82-
];
83-
84-
test.each(testTargets)('main client', (sdkClientMethodCSFactory) => {
77+
test('main client', () => {
8578
// @ts-expect-error
8679
const sdkClientMethod = sdkClientMethodCSFactory(params);
8780

@@ -106,21 +99,20 @@ describe('sdkClientMethodCSFactory', () => {
10699

107100
});
108101

109-
test.each(testTargets)('multiple clients', async (sdkClientMethodCSFactory, ignoresTT) => {
102+
test('multiple clients', async () => {
110103

111104
// @ts-expect-error
112105
const sdkClientMethod = sdkClientMethodCSFactory(params);
113106

114-
// calling the function with a diferent key than settings, should return a new client instance
107+
// calling the function with a different key than settings, should return a new client instance
115108
const newClients = new Set([
116-
sdkClientMethod('other-key'), // new client
117-
sdkClientMethod('other-key', 'other-tt'), // new client
118-
sdkClientMethod({ matchingKey: 'other-key', bucketingKey: 'buck' }) // new client
109+
sdkClientMethod('other-key'), // @ts-expect-error
110+
sdkClientMethod('other-key', 'ignored-tt'),
111+
sdkClientMethod({ matchingKey: 'other-key', bucketingKey: 'buck' })
119112
]);
120-
if (ignoresTT) expect(newClients.size).toBe(2);
121-
else expect(newClients.size).toBe(3);
113+
expect(newClients.size).toBe(2);
122114

123-
// each new client must follog the Client API
115+
// each new client must follow the Client API
124116
newClients.forEach(newClient => {
125117
assertClientApi(newClient);
126118
expect(newClient).not.toBe(sdkClientMethod());
@@ -150,7 +142,7 @@ describe('sdkClientMethodCSFactory', () => {
150142

151143
});
152144

153-
test.each(testTargets)('return main client instance if called with same key', (sdkClientMethodCSFactory) => {
145+
test('returns main client instance if called with same key', () => {
154146

155147
params.settings = settingsWithKey;
156148
// @ts-expect-error
@@ -163,20 +155,7 @@ describe('sdkClientMethodCSFactory', () => {
163155
expect(params.syncManager.shared).not.toBeCalled();
164156
});
165157

166-
test.each(testTargets)('return main client instance if called with same key and TT', (sdkClientMethodCSFactory) => {
167-
168-
params.settings = settingsWithKeyAndTT;
169-
// @ts-expect-error
170-
const sdkClientMethod = sdkClientMethodCSFactory(params);
171-
172-
expect(sdkClientMethod()).toBe(sdkClientMethod(settingsWithKeyAndTT.core.key, settingsWithKeyAndTT.core.trafficType));
173-
174-
expect(params.storage.shared).not.toBeCalled();
175-
expect(params.sdkReadinessManager.shared).not.toBeCalled();
176-
expect(params.syncManager.shared).not.toBeCalled();
177-
});
178-
179-
test.each(testTargets)('return main client instance if called with same key object', (sdkClientMethodCSFactory) => {
158+
test('returns main client instance if called with same key object', () => {
180159
// @ts-expect-error
181160
params.settings = settingsWithKeyObject;
182161
// @ts-expect-error
@@ -189,39 +168,37 @@ describe('sdkClientMethodCSFactory', () => {
189168
expect(params.syncManager.shared).not.toBeCalled();
190169
});
191170

192-
test.each(testTargets)('return same client instance if called with same key or traffic type (input validation)', (sdkClientMethodCSFactory, ignoresTT) => {
171+
test('returns same client instance if called with same key (input validation)', () => {
193172
// @ts-expect-error
194173
const sdkClientMethod = sdkClientMethodCSFactory(params);
195174

196-
const clientInstance = sdkClientMethod('key', 'tt');
175+
const clientInstance = sdkClientMethod('key');
197176

198-
expect(sdkClientMethod('key', 'tT')).toBe(clientInstance); // No new client created: TT is lowercased / ignored
199-
expect(sdkClientMethod(' key ', 'tt')).toBe(clientInstance); // No new client created: key is trimmed
200-
expect(sdkClientMethod({ matchingKey: 'key ', bucketingKey: ' key' }, 'TT')).toBe(clientInstance); // No new client created: key object is equivalent to 'key' string
177+
expect(sdkClientMethod('key')).toBe(clientInstance); // No new client created: same key
178+
expect(sdkClientMethod(' key ')).toBe(clientInstance); // No new client created: key is trimmed
179+
expect(sdkClientMethod({ matchingKey: 'key ', bucketingKey: ' key' })).toBe(clientInstance); // No new client created: key object is equivalent to 'key' string
201180

202181
expect(params.storage.shared).toBeCalledTimes(1);
203182
expect(params.sdkReadinessManager.shared).toBeCalledTimes(1);
204183
expect(params.syncManager.shared).toBeCalledTimes(1);
205184

206-
expect(sdkClientMethod('KEY', 'tt')).not.toBe(clientInstance); // New client created: key is case-sensitive
207-
if (!ignoresTT) expect(sdkClientMethod('key', 'TT ')).not.toBe(clientInstance); // New client created: TT is not trimmed
185+
expect(sdkClientMethod('KEY')).not.toBe(clientInstance); // New client created: key is case-sensitive
208186

209-
const clientCount = ignoresTT ? 2 : 3;
187+
const clientCount = 2;
210188
expect(params.storage.shared).toBeCalledTimes(clientCount);
211189
expect(params.sdkReadinessManager.shared).toBeCalledTimes(clientCount);
212190
expect(params.syncManager.shared).toBeCalledTimes(clientCount);
213191
});
214192

215-
test.each(testTargets)('invalid calls throw an error', (sdkClientMethodCSFactory, ignoresTT) => {
193+
test('invalid calls throw an error', () => {
216194
// @ts-expect-error
217-
const sdkClientMethod = sdkClientMethodCSFactory(params);
195+
const sdkClientMethod = sdkClientMethodCSFactory(params); // @ts-expect-error
218196
expect(() => sdkClientMethod({ matchingKey: settingsWithKey.core.key, bucketingKey: undefined })).toThrow('Shared Client needs a valid key.');
219-
if (!ignoresTT) expect(() => sdkClientMethod('valid-key', ['invalid-TT'])).toThrow('Shared Client needs a valid traffic type or no traffic type at all.');
220197
});
221198

222-
test.each(testTargets)('attributes binding - main client', (sdkClientMethodCSFactory) => {
199+
test('attributes binding - main client', () => {
223200
// @ts-expect-error
224-
const sdkClientMethod = sdkClientMethodCSFactory(params);
201+
const sdkClientMethod = sdkClientMethodCSFactory(params) as any;
225202

226203
// should return a function
227204
expect(typeof sdkClientMethod).toBe('function');
@@ -273,7 +250,7 @@ describe('sdkClientMethodCSFactory', () => {
273250
});
274251

275252

276-
test.each(testTargets)('attributes binding - shared clients', (sdkClientMethodCSFactory) => {
253+
test('attributes binding - shared clients', () => {
277254
// @ts-expect-error
278255
const sdkClientMethod = sdkClientMethodCSFactory(params);
279256

src/sdkClient/clientCS.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,17 @@ import { clientAttributesDecoration } from './clientAttributesDecoration';
55

66

77
/**
8-
* Decorator that binds a key and (optionally) a traffic type to client methods
8+
* Decorator that binds a key to client methods
99
*
1010
* @param client sync client instance
1111
* @param key validated split key
12-
* @param trafficType validated traffic type
1312
*/
14-
export function clientCSDecorator(log: ILogger, client: SplitIO.IClient, key: SplitIO.SplitKey, trafficType?: string): SplitIO.ICsClient {
13+
export function clientCSDecorator(log: ILogger, client: SplitIO.IClient, key: SplitIO.SplitKey): SplitIO.ICsClient {
1514

1615
let clientCS = clientAttributesDecoration(log, client);
1716

1817
return objectAssign(clientCS, {
19-
// In the client-side API, we bind a key to the client `getTreatment*` methods
18+
// In the client-side API, we bind a key to the client `getTreatment*` and `track` methods
2019
getTreatment: clientCS.getTreatment.bind(clientCS, key),
2120
getTreatmentWithConfig: clientCS.getTreatmentWithConfig.bind(clientCS, key),
2221
getTreatments: clientCS.getTreatments.bind(clientCS, key),
@@ -26,12 +25,10 @@ export function clientCSDecorator(log: ILogger, client: SplitIO.IClient, key: Sp
2625
getTreatmentsByFlagSet: clientCS.getTreatmentsByFlagSet.bind(clientCS, key),
2726
getTreatmentsWithConfigByFlagSet: clientCS.getTreatmentsWithConfigByFlagSet.bind(clientCS, key),
2827

29-
// Key is bound to the `track` method. Same thing happens with trafficType but only if provided
30-
track: trafficType ? clientCS.track.bind(clientCS, key, trafficType) : clientCS.track.bind(clientCS, key),
28+
track: clientCS.track.bind(clientCS, key),
3129

3230
// Not part of the public API. These properties are used to support other modules (e.g., Split Suite)
3331
isClientSide: true,
34-
key,
35-
trafficType
32+
key
3633
}) as SplitIO.ICsClient;
3734
}

src/sdkClient/sdkClientMethodCS.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: Spl
3535
return mainClientInstance;
3636
}
3737

38-
// Validate the key value. The trafficType (2nd argument) is ignored
38+
// Validate the key value
3939
const validKey = validateKey(log, key, LOG_PREFIX_CLIENT_INSTANTIATION);
4040
if (validKey === false) {
4141
throw new Error('Shared Client needs a valid key.');

src/sdkClient/sdkClientMethodCSWithTT.ts

Lines changed: 0 additions & 98 deletions
This file was deleted.

src/sdkFactory/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export interface ISdkFactoryParams {
9393

9494
// Sdk client method factory (ISDK::client method).
9595
// It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
96-
sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
96+
sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
9797

9898
// Impression observer factory.
9999
impressionsObserverFactory: () => IImpressionObserver

src/storages/KeyBuilderCS.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { KeyBuilder } from './KeyBuilder';
44
export interface MySegmentsKeyBuilder {
55
buildSegmentNameKey(segmentName: string): string;
66
extractSegmentName(builtSegmentKeyName: string): string | undefined;
7-
extractOldSegmentKey(builtSegmentKeyName: string): string | undefined;
87
buildTillKey(): string;
98
}
109

@@ -33,14 +32,6 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
3332
return builtSegmentKeyName.substr(prefix.length);
3433
}
3534

36-
// @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
37-
extractOldSegmentKey(builtSegmentKeyName: string) {
38-
const prefix = `${this.matchingKey}.${this.prefix}.segment.`;
39-
40-
if (startsWith(builtSegmentKeyName, prefix))
41-
return builtSegmentKeyName.substr(prefix.length);
42-
}
43-
4435
buildLastUpdatedKey() {
4536
return `${this.prefix}.splits.lastUpdated`;
4637
}
@@ -66,10 +57,6 @@ export function myLargeSegmentsKeyBuilder(prefix: string, matchingKey: string):
6657
if (startsWith(builtSegmentKeyName, p)) return builtSegmentKeyName.substr(p.length);
6758
},
6859

69-
extractOldSegmentKey() {
70-
return undefined;
71-
},
72-
7360
buildTillKey() {
7461
return `${prefix}.${matchingKey}.largeSegments.till`;
7562
}

src/storages/inLocalStorage/MySegmentsCacheInLocal.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,7 @@ export class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
5151
return Object.keys(localStorage).reduce((accum, key) => {
5252
let segmentName = this.keys.extractSegmentName(key);
5353

54-
if (segmentName) {
55-
accum.push(segmentName);
56-
} else {
57-
// @TODO @BREAKING: This is only to clean up "old" keys. Remove this whole else code block
58-
segmentName = this.keys.extractOldSegmentKey(key);
59-
60-
if (segmentName) { // this was an old segment key, let's clean up.
61-
const newSegmentKey = this.keys.buildSegmentNameKey(segmentName);
62-
try {
63-
// If the new format key is not there, create it.
64-
if (!localStorage.getItem(newSegmentKey)) {
65-
localStorage.setItem(newSegmentKey, DEFINED);
66-
// we are migrating a segment, let's track it.
67-
accum.push(segmentName);
68-
}
69-
localStorage.removeItem(key); // we migrated the current key, let's delete it.
70-
} catch (e) {
71-
this.log.error(e);
72-
}
73-
}
74-
}
54+
if (segmentName) accum.push(segmentName);
7555

7656
return accum;
7757
}, [] as string[]);

0 commit comments

Comments
 (0)