diff --git a/CHANGES.txt b/CHANGES.txt index 47660612..0f2bb0fd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +2.12.1 (April 30, 2026) + - Updated internal modules to handle `null` values from `/splitChanges` response. + - Updated some dependencies for vulnerability fixes. + 2.12.0 (February 24, 2026) - Added support for ioredis v5 (Related to issue https://github.com/splitio/javascript-commons/issues/471). diff --git a/package-lock.json b/package-lock.json index 4d1a6271..042598a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio-commons", - "version": "2.12.0", + "version": "2.12.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-commons", - "version": "2.12.0", + "version": "2.12.1", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -93,6 +93,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", "dev": true, + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.5", @@ -1562,6 +1563,7 @@ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.2.tgz", "integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==", "dev": true, + "peer": true, "dependencies": { "jest-diff": "^27.0.0", "pretty-format": "^27.0.0" @@ -1652,6 +1654,7 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -1765,9 +1768,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", "dev": true, "license": "MIT", "dependencies": { @@ -1863,6 +1866,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2204,10 +2208,11 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2250,6 +2255,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001663", "electron-to-chromium": "^1.5.28", @@ -2900,6 +2906,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -4605,6 +4612,7 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", "dev": true, + "peer": true, "dependencies": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", @@ -6661,6 +6669,7 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, + "peer": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -7792,6 +7801,7 @@ "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index fdac034d..074c7298 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "2.12.0", + "version": "2.12.1", "description": "Split JavaScript SDK common components", "main": "cjs/index.js", "module": "esm/index.js", diff --git a/src/dtos/types.ts b/src/dtos/types.ts index 2b0ee4ef..0887c6ca 100644 --- a/src/dtos/types.ts +++ b/src/dtos/types.ts @@ -232,8 +232,8 @@ export interface ISplit { trafficAllocationSeed?: number configurations?: { [treatmentName: string]: string - }, - sets?: string[], + } | null, + sets?: string[] | null, impressionsDisabled?: boolean } @@ -245,12 +245,12 @@ export interface ISplitChangesResponse { ff?: { t: number, s?: number, - d: ISplit[] + d?: ISplit[] | null, }, rbs?: { t: number, s?: number, - d: IRBSegment[] + d?: IRBSegment[] | null, } } diff --git a/src/storages/inLocalStorage/SplitsCacheInLocal.ts b/src/storages/inLocalStorage/SplitsCacheInLocal.ts index 30945684..19154070 100644 --- a/src/storages/inLocalStorage/SplitsCacheInLocal.ts +++ b/src/storages/inLocalStorage/SplitsCacheInLocal.ts @@ -205,7 +205,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync { }); } - private removeFromFlagSets(featureFlagName: string, flagSets?: string[]) { + private removeFromFlagSets(featureFlagName: string, flagSets?: string[] | null) { if (!flagSets) return; flagSets.forEach(flagSet => { diff --git a/src/storages/inMemory/SplitsCacheInMemory.ts b/src/storages/inMemory/SplitsCacheInMemory.ts index 461d15e6..71254b93 100644 --- a/src/storages/inMemory/SplitsCacheInMemory.ts +++ b/src/storages/inMemory/SplitsCacheInMemory.ts @@ -114,7 +114,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync { }); } - private removeFromFlagSets(featureFlagName: string, flagSets: string[] | undefined) { + private removeFromFlagSets(featureFlagName: string, flagSets?: string[] | null) { if (!flagSets) return; flagSets.forEach(flagSet => { this.removeNames(flagSet, featureFlagName); diff --git a/src/storages/inRedis/SplitsCacheInRedis.ts b/src/storages/inRedis/SplitsCacheInRedis.ts index 7258a770..85b07886 100644 --- a/src/storages/inRedis/SplitsCacheInRedis.ts +++ b/src/storages/inRedis/SplitsCacheInRedis.ts @@ -59,7 +59,7 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync { return this.redis.incr(ttKey); } - private _updateFlagSets(featureFlagName: string, flagSetsOfRemovedFlag?: string[], flagSetsOfAddedFlag?: string[]) { + private _updateFlagSets(featureFlagName: string, flagSetsOfRemovedFlag?: string[] | null, flagSetsOfAddedFlag?: string[] | null) { const removeFromFlagSets = returnDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag); let addToFlagSets = returnDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag); diff --git a/src/storages/pluggable/SplitsCachePluggable.ts b/src/storages/pluggable/SplitsCachePluggable.ts index 9b53f3a9..556d61cd 100644 --- a/src/storages/pluggable/SplitsCachePluggable.ts +++ b/src/storages/pluggable/SplitsCachePluggable.ts @@ -43,7 +43,7 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync { return this.wrapper.incr(ttKey); } - private _updateFlagSets(featureFlagName: string, flagSetsOfRemovedFlag?: string[], flagSetsOfAddedFlag?: string[]) { + private _updateFlagSets(featureFlagName: string, flagSetsOfRemovedFlag?: string[] | null, flagSetsOfAddedFlag?: string[] | null) { const removeFromFlagSets = returnDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag); let addToFlagSets = returnDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag); diff --git a/src/storages/setRolloutPlan.ts b/src/storages/setRolloutPlan.ts index a8529231..b92a1d8a 100644 --- a/src/storages/setRolloutPlan.ts +++ b/src/storages/setRolloutPlan.ts @@ -35,12 +35,12 @@ export function setRolloutPlan(log: ILogger, rolloutPlan: RolloutPlan, storage: if (splits && ff) { splits.clear(); - splits.update(ff.d, [], ff.t); + splits.update(ff.d || [], [], ff.t); } if (rbSegments && rbs) { rbSegments.clear(); - rbSegments.update(rbs.d, [], rbs.t); + rbSegments.update(rbs.d || [], [], rbs.t); } const segmentChanges = rolloutPlan.segmentChanges; diff --git a/src/sync/polling/updaters/splitChangesUpdater.ts b/src/sync/polling/updaters/splitChangesUpdater.ts index 0510a485..c84675dc 100644 --- a/src/sync/polling/updaters/splitChangesUpdater.ts +++ b/src/sync/polling/updaters/splitChangesUpdater.ts @@ -173,7 +173,7 @@ export function splitChangesUpdaterFactory( let updatedFlags: string[] = []; let ffUpdate: MaybeThenable = false; if (splitChanges.ff) { - const { added, removed, names } = computeMutation(splitChanges.ff.d, usedSegments, splitFiltersValidation); + const { added, removed, names } = computeMutation(splitChanges.ff.d || [], usedSegments, splitFiltersValidation); updatedFlags = names; log.debug(SYNC_SPLITS_UPDATE, [added.length, removed.length]); ffUpdate = splits.update(added, removed, splitChanges.ff.t); @@ -181,7 +181,7 @@ export function splitChangesUpdaterFactory( let rbsUpdate: MaybeThenable = false; if (splitChanges.rbs) { - const { added, removed } = computeMutation(splitChanges.rbs.d, usedSegments); + const { added, removed } = computeMutation(splitChanges.rbs.d || [], usedSegments); log.debug(SYNC_RBS_UPDATE, [added.length, removed.length]); rbsUpdate = rbSegments.update(added, removed, splitChanges.rbs.t); } diff --git a/src/utils/lang/__tests__/sets.spec.ts b/src/utils/lang/__tests__/sets.spec.ts index 8be359eb..f1141b10 100644 --- a/src/utils/lang/__tests__/sets.spec.ts +++ b/src/utils/lang/__tests__/sets.spec.ts @@ -23,4 +23,6 @@ test('returnDifference', () => { expect(returnDifference([], [])).toEqual([]); expect(returnDifference(list, [])).toEqual(list); expect(returnDifference([], list2)).toEqual([]); + + expect(returnDifference(undefined, null)).toEqual([]); }); diff --git a/src/utils/lang/sets.ts b/src/utils/lang/sets.ts index 5015a0fc..13bcfe43 100644 --- a/src/utils/lang/sets.ts +++ b/src/utils/lang/sets.ts @@ -12,6 +12,8 @@ export function returnSetsUnion(set: Set, set2: Set): Set { return new Set(setToArray(set).concat(setToArray(set2))); } -export function returnDifference(list: T[] = [], list2: T[] = []): T[] { - return list.filter(item => list2.indexOf(item) === -1); +export function returnDifference(list1?: T[] | null, list2?: T[] | null): T[] { + list1 = list1 || []; + list2 = list2 || []; + return list1.filter(item => list2!.indexOf(item) === -1); }