From 0a082b20110cb321418d85eedb979884058f86e0 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 4 Oct 2024 18:45:54 -0300 Subject: [PATCH 01/20] Rename dist folders: /lib -> /cjs, /es -> /esm --- .gitignore | 4 ++-- CHANGES.txt | 4 +++- client/package.json | 4 ++-- lib/factory/package.json | 4 ++++ lib/platform/getEventSource/package.json | 4 ++++ lib/platform/getFetch/package.json | 4 ++++ lib/platform/package.json | 4 ++++ lib/settings/package.json | 4 ++++ package.json | 14 +++++++------- scripts/build_cjs_replace_imports.sh | 4 ++-- scripts/build_esm_replace_imports.sh | 4 ++-- scripts/copy.packages.json.js | 4 ++-- server/package.json | 4 ++-- webpack.common.js | 2 +- 14 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 lib/factory/package.json create mode 100644 lib/platform/getEventSource/package.json create mode 100644 lib/platform/getFetch/package.json create mode 100644 lib/platform/package.json create mode 100644 lib/settings/package.json diff --git a/.gitignore b/.gitignore index 376800e23..f26a161f7 100644 --- a/.gitignore +++ b/.gitignore @@ -19,8 +19,8 @@ dump.rdb /stats ## transpiled code -/lib -/es +/cjs +/esm /umd ## TS tests compilated files diff --git a/CHANGES.txt b/CHANGES.txt index 1453141e9..22397f752 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,7 +1,9 @@ -10.29.0 (September XX, 2024) +11.0.0 (October XX, 2024) - Updated @splitsoftware/splitio-commons package to version 1.18.0 that includes minor updates: - Added support for targeting rules based on large segments for browsers. - Updated some transitive dependencies for vulnerability fixes. + - BREAKING CHANGES: + - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. 10.28.0 (September 6, 2024) - Updated @splitsoftware/splitio-commons package to version 1.17.0 that includes minor updates: diff --git a/client/package.json b/client/package.json index d1f660668..f99b69ceb 100644 --- a/client/package.json +++ b/client/package.json @@ -1,5 +1,5 @@ { - "main": "../lib/factory/browser.js", - "module": "../es/factory/browser.js", + "main": "../cjs/factory/browser.js", + "module": "../esm/factory/browser.js", "types": "../types/client/index.d.ts" } diff --git a/lib/factory/package.json b/lib/factory/package.json new file mode 100644 index 000000000..a19625907 --- /dev/null +++ b/lib/factory/package.json @@ -0,0 +1,4 @@ +{ + "main": "./node.js", + "browser": "./browser.js" +} diff --git a/lib/platform/getEventSource/package.json b/lib/platform/getEventSource/package.json new file mode 100644 index 000000000..a19625907 --- /dev/null +++ b/lib/platform/getEventSource/package.json @@ -0,0 +1,4 @@ +{ + "main": "./node.js", + "browser": "./browser.js" +} diff --git a/lib/platform/getFetch/package.json b/lib/platform/getFetch/package.json new file mode 100644 index 000000000..a19625907 --- /dev/null +++ b/lib/platform/getFetch/package.json @@ -0,0 +1,4 @@ +{ + "main": "./node.js", + "browser": "./browser.js" +} diff --git a/lib/platform/package.json b/lib/platform/package.json new file mode 100644 index 000000000..a19625907 --- /dev/null +++ b/lib/platform/package.json @@ -0,0 +1,4 @@ +{ + "main": "./node.js", + "browser": "./browser.js" +} diff --git a/lib/settings/package.json b/lib/settings/package.json new file mode 100644 index 000000000..a19625907 --- /dev/null +++ b/lib/settings/package.json @@ -0,0 +1,4 @@ +{ + "main": "./node.js", + "browser": "./browser.js" +} diff --git a/package.json b/package.json index 95344a2b8..0e1ba9135 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "CONTRIBUTORS-GUIDE.md", "LICENSE", "CHANGES.txt", - "lib", + "cjs", "types", - "es", + "esm", "src", "scripts/ga-to-split-autorequire.js", "client", @@ -32,8 +32,8 @@ "sdk", "javascript" ], - "main": "lib/index.js", - "module": "es/index.js", + "main": "cjs/index.js", + "module": "esm/index.js", "types": "types", "engines": { "npm": ">=3", @@ -84,10 +84,10 @@ "webpack-merge": "^5.8.0" }, "scripts": { - "build-esm": "rimraf es && tsc -outDir es", - "postbuild-esm": "cross-env NODE_ENV=es node scripts/copy.packages.json.js && ./scripts/build_esm_replace_imports.sh", + "build-esm": "rimraf esm && tsc -outDir esm", + "postbuild-esm": "cross-env NODE_ENV=esm node scripts/copy.packages.json.js && ./scripts/build_esm_replace_imports.sh", "build-umd:stats": "webpack --progress --env production --json > ./stats/stat_results.json", - "build-cjs": "rimraf lib && tsc -outDir lib -m CommonJS", + "build-cjs": "rimraf cjs && tsc -outDir cjs -m CommonJS", "postbuild-cjs": "cross-env NODE_ENV=cjs node scripts/copy.packages.json.js && ./scripts/build_cjs_replace_imports.sh", "build-umd": "rimraf umd && webpack --config webpack.dev.js --env branch=$BUILD_BRANCH && webpack --config webpack.prod.js --env branch=$BUILD_BRANCH && ./scripts/clean_umd_build.sh", "build:npm": "npm run build-cjs && npm run build-esm", diff --git a/scripts/build_cjs_replace_imports.sh b/scripts/build_cjs_replace_imports.sh index 85490429f..fd29a4a7e 100755 --- a/scripts/build_cjs_replace_imports.sh +++ b/scripts/build_cjs_replace_imports.sh @@ -1,7 +1,7 @@ #!/bin/bash -# replace splitio-commons imports to use ES modules -replace '@splitsoftware/splitio-commons/src' '@splitsoftware/splitio-commons/cjs' ./lib -r +# replace splitio-commons imports to use CommonJS +replace '@splitsoftware/splitio-commons/src' '@splitsoftware/splitio-commons/cjs' ./cjs -r if [ $? -eq 0 ] then diff --git a/scripts/build_esm_replace_imports.sh b/scripts/build_esm_replace_imports.sh index 81cfb81b0..16155e206 100755 --- a/scripts/build_esm_replace_imports.sh +++ b/scripts/build_esm_replace_imports.sh @@ -1,7 +1,7 @@ #!/bin/bash -# replace splitio-commons imports to use ES modules -replace '@splitsoftware/splitio-commons/src' '@splitsoftware/splitio-commons/esm' ./es -r +# replace splitio-commons imports to use EcmaScript Modules +replace '@splitsoftware/splitio-commons/src' '@splitsoftware/splitio-commons/esm' ./esm -r if [ $? -eq 0 ] then diff --git a/scripts/copy.packages.json.js b/scripts/copy.packages.json.js index 3ce08513b..68683ee6c 100644 --- a/scripts/copy.packages.json.js +++ b/scripts/copy.packages.json.js @@ -3,8 +3,8 @@ const copyfiles = require('copyfiles'); const input = './src/**/package.json'; -const outputCjsDir = './lib'; -const outputEsmDir = './es'; +const outputCjsDir = './cjs'; +const outputEsmDir = './esm'; copyfiles([input, process.env.NODE_ENV === 'cjs' ? outputCjsDir : outputEsmDir], { up: 1, diff --git a/server/package.json b/server/package.json index be8f299ed..21aeb6f1f 100644 --- a/server/package.json +++ b/server/package.json @@ -1,5 +1,5 @@ { - "main": "../lib/factory/node.js", - "module": "../es/factory/node.js", + "main": "../cjs/factory/node.js", + "module": "../esm/factory/node.js", "types": "../types/server/index.d.ts" } diff --git a/webpack.common.js b/webpack.common.js index e7a389788..8fb8dc34b 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,6 +1,6 @@ module.exports = { entry: { - split: ['./es/umd.js'] + split: ['./esm/umd.js'] }, output: { From 4cfec031a698676012ac074c1f33a173fafce89b Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 4 Oct 2024 18:54:01 -0300 Subject: [PATCH 02/20] Drop support for NodeJS v6 --- CHANGES.txt | 1 + package.json | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 22397f752..d6c991560 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,7 @@ - Updated some transitive dependencies for vulnerability fixes. - BREAKING CHANGES: - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. + - Drop support for NodeJS v6. The SDK now requires NodeJS v14 or above. 10.28.0 (September 6, 2024) - Updated @splitsoftware/splitio-commons package to version 1.17.0 that includes minor updates: diff --git a/package.json b/package.json index 0e1ba9135..99415e656 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,7 @@ "module": "esm/index.js", "types": "types", "engines": { - "npm": ">=3", - "node": ">=6" + "node": ">=14.0.0" }, "dependencies": { "@splitsoftware/splitio-commons": "1.17.1-rc.0", From 9eefd1bf415e0ef35512e9aea806c849cac27f76 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 8 Oct 2024 17:50:58 -0300 Subject: [PATCH 03/20] Upgrade JS-commons. Updated type definitions & tests --- karma/e2e.gaIntegration.karma.conf.js | 20 - package-lock.json | 100 ++-- package.json | 8 +- scripts/ga-to-split-autorequire.js | 1 - src/__tests__/browserSuites/telemetry.spec.js | 2 +- .../browserSuites/user-consent.spec.js | 10 +- .../gaIntegration/both-integrations.spec.js | 138 ------ src/__tests__/gaIntegration/browser.spec.js | 31 -- .../gaIntegration/ga-to-split.spec.js | 461 ------------------ src/__tests__/gaIntegration/gaTestUtils.js | 94 ---- .../gaIntegration/split-to-ga.spec.js | 438 ----------------- src/__tests__/online/browser.spec.js | 8 +- src/__tests__/testUtils/index.js | 2 +- src/factory/browser.js | 5 +- src/settings/__tests__/browser.spec.js | 30 -- src/settings/browser.js | 4 +- src/settings/defaults/version.js | 2 +- src/sync/offline/splitsParserFromFile.js | 2 +- ts-tests/index.ts | 88 +--- types/client/index.d.ts | 2 +- types/index.d.ts | 6 +- types/server/index.d.ts | 4 +- types/splitio.d.ts | 445 +++++------------ 23 files changed, 226 insertions(+), 1675 deletions(-) delete mode 100644 karma/e2e.gaIntegration.karma.conf.js delete mode 100644 scripts/ga-to-split-autorequire.js delete mode 100644 src/__tests__/gaIntegration/both-integrations.spec.js delete mode 100644 src/__tests__/gaIntegration/browser.spec.js delete mode 100644 src/__tests__/gaIntegration/ga-to-split.spec.js delete mode 100644 src/__tests__/gaIntegration/gaTestUtils.js delete mode 100644 src/__tests__/gaIntegration/split-to-ga.spec.js diff --git a/karma/e2e.gaIntegration.karma.conf.js b/karma/e2e.gaIntegration.karma.conf.js deleted file mode 100644 index f6b03110f..000000000 --- a/karma/e2e.gaIntegration.karma.conf.js +++ /dev/null @@ -1,20 +0,0 @@ -const assign = require('lodash/assign'); - -module.exports = function(config) { - 'use strict'; - - config.set(assign({}, require('./config'), { - // list of files / patterns to load in the browser - files: [ - '__tests__/gaIntegration/browser.spec.js' - ], - // prepare code for the browser using webpack - preprocessors: { - '__tests__/gaIntegration/browser.spec.js': ['webpack'] - }, - - // level of logging - // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG - logLevel: config.LOG_WARN - })); -}; diff --git a/package-lock.json b/package-lock.json index 4fce49522..4071ba591 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.2", + "version": "11.0.0-rc.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.2", + "version": "11.0.0-rc.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "1.17.1-rc.1", - "@types/google.analytics": "0.0.40", + "@splitsoftware/splitio-commons": "2.0.0-rc.0", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", @@ -53,8 +52,7 @@ "webpack-merge": "^5.8.0" }, "engines": { - "node": ">=6", - "npm": ">=3" + "node": ">=14.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -872,9 +870,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "1.17.1-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.1.tgz", - "integrity": "sha512-mmDcWW2iyqQF/FzLgPoRA3KXpvswk/sDIhQGWTg3WPkapnA+e4WXb+U/TSGGB/Ig88NlM76FlxMDkrHnBayDXg==", + "version": "2.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.0.tgz", + "integrity": "sha512-iNuGugPMXQ/+k+uSDyhsvwkaGdzQrRaxRtP1sv58STKQFwww1smPxRA1gKfawoQm04quEHtLMKYm25t6VL0fJw==", "dependencies": { "tslib": "^2.3.1" }, @@ -932,11 +930,6 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, - "node_modules/@types/google.analytics": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz", - "integrity": "sha512-R3HpnLkqmKxhUAf8kIVvDVGJqPtaaZlW4yowNwjOZUTmYUQEgHh8Nh5wkSXKMroNAuQM8gbXJHmNbbgA8tdb7Q==" - }, "node_modules/@types/ioredis": { "version": "4.28.10", "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", @@ -2612,9 +2605,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.1.tgz", + "integrity": "sha512-NEpDCw9hrvBW+hVEOK4T7v0jFJ++KgtPl4jKFwsZVfG1XhS0dCrSb3VMb9gPAd7VAdW52VT1EnaNiU2vM8C0og==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -2633,9 +2626,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true, "engines": { "node": ">=10.0.0" @@ -4473,9 +4466,9 @@ "dev": true }, "node_modules/karma": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", - "integrity": "sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.4.tgz", + "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "dependencies": { "@colors/colors": "1.5.0", @@ -4497,7 +4490,7 @@ "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", - "socket.io": "^4.4.1", + "socket.io": "^4.7.2", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", @@ -4951,9 +4944,9 @@ "dev": true }, "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, "dependencies": { "isarray": "0.0.1" @@ -6435,16 +6428,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", + "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -8528,9 +8521,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.17.1-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.1.tgz", - "integrity": "sha512-mmDcWW2iyqQF/FzLgPoRA3KXpvswk/sDIhQGWTg3WPkapnA+e4WXb+U/TSGGB/Ig88NlM76FlxMDkrHnBayDXg==", + "version": "2.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.0.tgz", + "integrity": "sha512-iNuGugPMXQ/+k+uSDyhsvwkaGdzQrRaxRtP1sv58STKQFwww1smPxRA1gKfawoQm04quEHtLMKYm25t6VL0fJw==", "requires": { "tslib": "^2.3.1" } @@ -8580,11 +8573,6 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, - "@types/google.analytics": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz", - "integrity": "sha512-R3HpnLkqmKxhUAf8kIVvDVGJqPtaaZlW4yowNwjOZUTmYUQEgHh8Nh5wkSXKMroNAuQM8gbXJHmNbbgA8tdb7Q==" - }, "@types/ioredis": { "version": "4.28.10", "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", @@ -9954,9 +9942,9 @@ } }, "engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.1.tgz", + "integrity": "sha512-NEpDCw9hrvBW+hVEOK4T7v0jFJ++KgtPl4jKFwsZVfG1XhS0dCrSb3VMb9gPAd7VAdW52VT1EnaNiU2vM8C0og==", "dev": true, "requires": { "@types/cookie": "^0.4.1", @@ -9981,9 +9969,9 @@ } }, "engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true }, "enhanced-resolve": { @@ -11305,9 +11293,9 @@ "dev": true }, "karma": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", - "integrity": "sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.4.tgz", + "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "requires": { "@colors/colors": "1.5.0", @@ -11329,7 +11317,7 @@ "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", - "socket.io": "^4.4.1", + "socket.io": "^4.7.2", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", @@ -11715,9 +11703,9 @@ "dev": true }, "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, "requires": { "isarray": "0.0.1" @@ -12848,16 +12836,16 @@ } }, "socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", + "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" } diff --git a/package.json b/package.json index 72ac785c0..12856a9ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.2", + "version": "11.0.0-rc.0", "description": "Split SDK", "files": [ "README.md", @@ -11,7 +11,6 @@ "types", "esm", "src", - "scripts/ga-to-split-autorequire.js", "client", "server" ], @@ -39,8 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "1.17.1-rc.1", - "@types/google.analytics": "0.0.40", + "@splitsoftware/splitio-commons": "2.0.0-rc.0", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", @@ -90,7 +88,6 @@ "postbuild-cjs": "cross-env NODE_ENV=cjs node scripts/copy.packages.json.js && ./scripts/build_cjs_replace_imports.sh", "build-umd": "rimraf umd && webpack --config webpack.dev.js --env branch=$BUILD_BRANCH && webpack --config webpack.prod.js --env branch=$BUILD_BRANCH && ./scripts/clean_umd_build.sh", "build:npm": "npm run build-cjs && npm run build-esm", - "build:ga-to-split-autorequire": "terser ./node_modules/@splitsoftware/splitio-commons/src/integrations/ga/autoRequire.js --mangle --output ./scripts/ga-to-split-autorequire.js && cp ./scripts/ga-to-split-autorequire.js umd/ga-to-split-autorequire.js", "build": "npm run build-cjs && npm run build-esm && npm run build-umd", "check": "npm run check:lint && npm run check:version", "check:lint": "eslint src", @@ -103,7 +100,6 @@ "test-browser-e2e-destroy": "cross-env NODE_ENV=test karma start karma/e2e.destroy.karma.conf.js", "test-browser-e2e-errorCatching": "cross-env NODE_ENV=test karma start karma/e2e.errorCatching.karma.conf.js", "test-browser-e2e-push": "cross-env NODE_ENV=test karma start karma/e2e.push.karma.conf.js", - "test-browser-e2e-gaIntegration": "cross-env NODE_ENV=test karma start karma/e2e.gaIntegration.karma.conf.js", "test-node": "npm run test-node-unit && npm run test-node-e2e", "test-node-unit": "cross-env NODE_ENV=test tape -r ./ts-node.register \"src/*/**/__tests__/**/!(browser).spec.js\" | tap-min", "test-node-e2e": "npm run test-node-e2e-online && npm run test-node-e2e-offline && npm run test-node-e2e-destroy && npm run test-node-e2e-errorCatching && npm run test-node-e2e-push && npm run test-node-e2e-redis", diff --git a/scripts/ga-to-split-autorequire.js b/scripts/ga-to-split-autorequire.js deleted file mode 100644 index 7f8b88597..000000000 --- a/scripts/ga-to-split-autorequire.js +++ /dev/null @@ -1 +0,0 @@ -(function(n,t,e){n[e]=n[e]||t;n[t]=n[t]||function(){n[t].q.push(arguments)};n[t].q=n[t].q||[];var r={};function i(n){return typeof n==="object"&&typeof n.name==="string"&&n.name}function o(e){if(e&&e[0]==="create"){var o=i(e[1])||i(e[2])||i(e[3])||(typeof e[3]==="string"?e[3]:undefined);if(!r[o]){r[o]=true;n[t]((o?o+".":"")+"require","splitTracker")}}}n[t].q.forEach(o);var u=n[t].q.push;n[t].q.push=function(n){var t=u.apply(this,arguments);o(n);return t}})(window,"ga","GoogleAnalyticsObject"); \ No newline at end of file diff --git a/src/__tests__/browserSuites/telemetry.spec.js b/src/__tests__/browserSuites/telemetry.spec.js index 0251dc0f2..5ed7c331d 100644 --- a/src/__tests__/browserSuites/telemetry.spec.js +++ b/src/__tests__/browserSuites/telemetry.spec.js @@ -111,7 +111,7 @@ export default async function telemetryBrowserSuite(fetchMock, t) { oM: 0, st: 'memory', aF: 1, rF: 0, sE: false, rR: { sp: 99999, ms: 60, im: 300, ev: 60, te: 1 } /* override featuresRefreshRate */, uO: { s: true, e: true, a: false, st: false, t: true } /* override sdk, events and telemetry URLs */, - iQ: 30000, eQ: 500, iM: 0, iL: false, hP: false, nR: 1 /* 1 non ready usage */, t: [], i: [], uC: 2 /* Default GRANTED */, + iQ: 30000, eQ: 500, iM: 0, iL: false, hP: false, nR: 1 /* 1 non ready usage */, t: [], uC: 2 /* Default GRANTED */, fsT: 0, fsI: 0 }, 'metrics/config JSON payload should be the expected'); diff --git a/src/__tests__/browserSuites/user-consent.spec.js b/src/__tests__/browserSuites/user-consent.spec.js index 024fcb44d..ed1caba2c 100644 --- a/src/__tests__/browserSuites/user-consent.spec.js +++ b/src/__tests__/browserSuites/user-consent.spec.js @@ -72,7 +72,7 @@ function mockSubmittersRequests(fetchMock, assert, impressionFeature, eventTypeI export default function userConsent(fetchMock, t) { - // Validate trackers, submitters and browser listener behaviour on different consent status transitions + // Validate trackers, submitters and browser listener behavior on different consent status transitions t.test(async (assert) => { const sendBeaconSpy = sinon.spy(window.navigator, 'sendBeacon'); let expectedTrackedImpressions = 0; @@ -97,7 +97,7 @@ export default function userConsent(fetchMock, t) { ], ['on', 'on', 'on', 'on', 'on', 'on', 'on', 'on'], 'evaluating on SDK ready'); if (isTracking) expectedTrackedImpressions += 8; - // Trigger pagehide event to validate browser listener behaviour + // Trigger pagehide event to validate browser listener behavior // Beacon API is used only if user consent is GRANTED triggerPagehideEvent(); if (factory.UserConsent.getStatus() === factory.UserConsent.Status.GRANTED) { @@ -137,9 +137,9 @@ export default function userConsent(fetchMock, t) { assert.equal(trackedImpressions.length, expectedTrackedImpressions, 'Tracked impressions are the expected'); sendBeaconSpy.restore(); assert.end(); - }, 'Validate trackers, submitters and browser listener behaviour on different consent status transitions'); + }, 'Validate trackers, submitters and browser listener behavior on different consent status transitions'); - // Validate submitter's behaviour with full queues and with events first push window + // Validate submitter's behavior with full queues and with events first push window t.test(async (assert) => { const config = { ...baseConfig, @@ -182,6 +182,6 @@ export default function userConsent(fetchMock, t) { await client.destroy(); assert.end(); - }, 'Validate submitter\'s behaviour with full queues and with events first push window'); + }, 'Validate submitter\'s behavior with full queues and with events first push window'); } diff --git a/src/__tests__/gaIntegration/both-integrations.spec.js b/src/__tests__/gaIntegration/both-integrations.spec.js deleted file mode 100644 index 17b4ae736..000000000 --- a/src/__tests__/gaIntegration/both-integrations.spec.js +++ /dev/null @@ -1,138 +0,0 @@ -import { SplitFactory } from '../../'; -import { settingsFactory } from '../../settings'; -import { gaSpy, gaTag } from './gaTestUtils'; -import includes from 'lodash/includes'; -import { DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; -import { url } from '../testUtils'; - -function countImpressions(parsedImpressionsBulkPayload) { - return parsedImpressionsBulkPayload - .reduce((accumulator, currentValue) => { return accumulator + currentValue.i.length; }, 0); -} - -const config = { - core: { - key: 'facundo@split.io', - trafficType: 'user', - }, - integrations: [{ - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - }, { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - }], - streamingEnabled: false, - sync: { - impressionsMode: DEBUG, - } -}; -const settings = settingsFactory(config); - -export default function (fetchMock, assert) { - - let client; - - // test default behavior of both integrations - assert.test(t => { - const customHits = [{ hitType: 'pageview' }, { hitType: 'event' }]; - - /* [eventType] */ - const splitTrackParams = [['some_event'], ['other_event'], ['another_event']]; - /* [splitName] */ - const splitGetTreatmentParams = [['hierarchical_splits_test']]; - - // Generator to synchronize the call of t.end() when both impressions and events endpoints were invoked. - const finish = (function* () { - yield; - const totalHits = customHits.length + splitTrackParams.length + splitGetTreatmentParams.length; - - t.equal(window.gaSpy.getHits().length, totalHits, 'Total hits'); - setTimeout(() => { - client.destroy(); - t.end(); - }, 0); - })(); - - fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, opts) => { - // we can assert payload and ga hits, once ga is ready and after `SplitToGa.queue`, that is timeout wrapped, make to the queue stack. - window.ga(() => { - setTimeout(() => { - try { - const resp = JSON.parse(opts.body); - const numberOfSentImpressions = countImpressions(resp); - const sentImpressionHits = window.gaSpy.getHits().filter(hit => hit.eventCategory === 'split-impression'); - - t.equal(numberOfSentImpressions, splitGetTreatmentParams.length, 'Number of impressions'); - t.equal(sentImpressionHits.length, splitGetTreatmentParams.length, `Number of sent impression hits must be equal to the number of impressions (${splitGetTreatmentParams.length})`); - - finish.next(); - } catch (err) { - console.error(err); - } - }); - }); - return 200; - }); - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - window.ga(() => { - setTimeout(() => { - try { - const sentEvents = JSON.parse(opts.body); - const sentEventsFromSplitToGa = sentEvents.filter(event => { - return event.properties && event.properties.eventCategory && includes(event.properties.eventCategory, 'split'); - }); - - t.equal(sentEvents.length, splitTrackParams.length + customHits.length, 'Number of sent events is equal to custom events plus hits tracked as events'); - t.equal(sentEventsFromSplitToGa.length, 0, 'GA hits comming from Split-to-GA integration must not be tracked again as Split events'); - - const sentHitsNoSplitData = window.gaSpy.getHits().filter(hit => !hit.eventCategory || !includes(hit.eventCategory, 'split')); - const sentHitsSplitEvents = window.gaSpy.getHits().filter(hit => hit.eventCategory === 'split-event'); - - t.equal(sentHitsNoSplitData.length, customHits.length, 'Number of custom hits'); - t.equal(sentHitsSplitEvents.length, splitTrackParams.length, 'Number of Split event hits'); - finish.next(); - } catch (err) { - console.error(err); - } - }); - }); - return 200; - }); - - gaTag(); - - // siteSpeedSampleRate set to 0 to never send a site speed timing hit - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - - gaSpy(); - - window.ga('require', 'splitTracker'); - customHits.forEach(hit => { - window.ga('send', hit); - }); - - const factory = SplitFactory({ - ...config, - startup: { - eventsFirstPushWindow: 0, - }, - scheduler: { - impressionsRefreshRate: 1, - // @TODO eventsPushRate is too high, but using eventsQueueSize don't let us assert `filterSplitToGaHits` - eventsPushRate: 10, - // eventsQueueSize: splitTrackParams.length + customHits.length, - }, - }); - client = factory.client(); - - client.ready().then(() => { - splitTrackParams.forEach(trackParams => { - client.track.apply(client, trackParams); - }); - splitGetTreatmentParams.forEach(getTreatmentParams => { - client.getTreatment.apply(client, getTreatmentParams); - }); - }); - }); - -} diff --git a/src/__tests__/gaIntegration/browser.spec.js b/src/__tests__/gaIntegration/browser.spec.js deleted file mode 100644 index 502d57c29..000000000 --- a/src/__tests__/gaIntegration/browser.spec.js +++ /dev/null @@ -1,31 +0,0 @@ -import tape from 'tape-catch'; -import fetchMock from '../testUtils/fetchMock'; -import { url } from '../testUtils'; -import gaToSplitSuite from './ga-to-split.spec'; -import splitToGaSuite from './split-to-ga.spec'; -import bothIntegrationsSuite from './both-integrations.spec'; - -import { settingsFactory } from '../../settings'; - -import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; -import membershipsFacundo from '../mocks/memberships.facundo@split.io.json'; - -const settings = settingsFactory({ - core: { - key: 'facundo@split.io' - } -}); - -tape('## E2E CI Tests ##', function (assert) { - - fetchMock.get(url(settings, '/splitChanges?s=1.2&since=-1'), { status: 200, body: splitChangesMock1 }); - fetchMock.get(url(settings, '/memberships/facundo%40split.io'), { status: 200, body: membershipsFacundo }); - fetchMock.post(/\/v1\/metrics/, 200); // 0.1% sample rate - - /* Validate GA integration */ - assert.test('E2E / GA-to-Split', gaToSplitSuite.bind(null, fetchMock)); - assert.test('E2E / Split-to-GA', splitToGaSuite.bind(null, fetchMock)); - assert.test('E2E / Both GA integrations', bothIntegrationsSuite.bind(null, fetchMock)); - - assert.end(); -}); diff --git a/src/__tests__/gaIntegration/ga-to-split.spec.js b/src/__tests__/gaIntegration/ga-to-split.spec.js deleted file mode 100644 index cc8e8764f..000000000 --- a/src/__tests__/gaIntegration/ga-to-split.spec.js +++ /dev/null @@ -1,461 +0,0 @@ -import sinon from 'sinon'; -import { SplitFactory } from '../../'; -import { settingsFactory } from '../../settings'; -import { gaSpy, gaTag, addGaTag, removeGaTag } from './gaTestUtils'; -import { url } from '../testUtils'; - -const config = { - core: { - key: 'facundo@split.io', - trafficType: 'user', - }, - integrations: [{ - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - }], - startup: { - eventsFirstPushWindow: 0.2, - }, - streamingEnabled: false -}; -const settings = settingsFactory(config); - -export default function (fetchMock, assert) { - - let client; - - // test default behavior on default tracker - assert.test(t => { - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - const sentHits = window.gaSpy.getHits(); - - t.equal(resp.length, sentHits.length, `Number of sent hits must be equal to sent events (${resp.length})`); - t.equal(resp[0].key, settings.core.key, 'Event key is same that SDK config key'); - t.equal(resp[0].trafficTypeName, settings.core.trafficType, 'Event trafficTypeName is same that SDK config key'); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - return 200; - }); - - gaTag(); - - // siteSpeedSampleRate set to 0 to never send a site speed timing hit - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - - gaSpy(); - - window.ga('require', 'splitTracker'); - window.ga('send', 'pageview'); - - const factory = SplitFactory(config); - client = factory.client(); - - }); - - // test default behavior on named tracker, tracking N events, and GA in a different global variable - assert.test(t => { - const numberOfCustomEvents = 5; - let client; - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - const sentHits = window.gaSpy.getHits('myTracker'); - - t.equal(resp.length, sentHits.length, `Number of sent hits must be equal to sent events (${resp.length})`); - t.equal(resp[0].key, settings.core.key, 'Event key is same that SDK config key'); - t.equal(resp[0].trafficTypeName, settings.core.trafficType, 'Event trafficTypeName is same that SDK config key'); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - return 200; - }); - - gaTag('other_location_for_ga'); - - window.other_location_for_ga('create', 'UA-00000001-1', 'example1.com', 'myTracker', { siteSpeedSampleRate: 0 }); - - gaSpy(['myTracker']); - - const factory = SplitFactory(config); - client = factory.client(); - - window.other_location_for_ga('myTracker.require', 'splitTracker'); - // this second 'require' is not applied (does not overwrite previous command) - window.other_location_for_ga('myTracker.require', 'splitTracker', { mapper: function () { throw 'error'; } }); - - for (let i = 0; i < numberOfCustomEvents; i++) - window.other_location_for_ga('myTracker.send', 'pageview'); - - }); - - // test error: no TT in SDK config - assert.test(t => { - const numberOfCustomEvents = 5; - - gaTag(); - - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - - gaSpy(); - - const logSpy = sinon.spy(console, 'log'); - - const factory = SplitFactory({ - ...config, - core: { key: config.core.key }, - debug: true, - }); - - window.ga('require', 'splitTracker'); - for (let i = 0; i < numberOfCustomEvents; i++) - window.ga('send', 'pageview'); - - // We must wait until ga is ready to get SplitTracker required and invoked, and to assert the test - window.ga(() => { - t.ok(logSpy.calledWith('[WARN] splitio => ga-to-split: No valid identities were provided. Please check that you are passing a valid list of identities or providing a traffic type at the SDK configuration.')); - t.equal(window.gaSpy.getHits().length, numberOfCustomEvents, `Number of sent hits must be equal to ${numberOfCustomEvents}`); - - logSpy.restore(); - t.end(); - }); - - factory.client().destroy(); - - }); - - // test default behavior, providing a list of identities as SDK options - assert.test(t => { - const numberOfCustomEvents = 3; - const identities = [{ key: 'user1', trafficType: 'user' }, { key: 'user2', trafficType: 'user' }]; - let client; - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - const sentHits = window.gaSpy.getHits('myTracker3'); - - t.equal(sentHits.length, numberOfCustomEvents, `Number of sent hits must be equal to sent custom events (${numberOfCustomEvents})`); - t.equal(resp.length, numberOfCustomEvents * identities.length, 'The number of sent events must be equal to the number of sent hits multiply by the number of identities'); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - return 200; - }); - - gaTag(); - - window.ga('create', 'UA-00000003-1', 'example3.com', 'myTracker3', { siteSpeedSampleRate: 0 }); - - gaSpy(['myTracker3']); - - const factory = SplitFactory({ - ...config, - core: { key: config.core.key }, - integrations: [{ - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - identities: identities, - }], - }); - client = factory.client(); - - window.ga('myTracker3.require', 'splitTracker'); - for (let i = 0; i < numberOfCustomEvents; i++) - window.ga('myTracker3.send', 'pageview'); - - }); - - - // test default behavior in multiple trackers, providing a list of identities in plugin options for one tracker and in sdk options for another - assert.test(t => { - const identitiesPluginOpts = [{ key: 'user1', trafficType: 'user' }, { key: 'user2', trafficType: 'user' }]; - const identitiesSdkOpts = [{ key: 'user3', trafficType: 'user' }]; - const gaSendIterations = 3; - const expectedNumberOfSplitEvents = gaSendIterations * (identitiesPluginOpts.length + identitiesSdkOpts.length); - - let client; - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - t.equal(resp.length, expectedNumberOfSplitEvents, 'The number of sent Split events must be equal to the number of sent hits multiply by the number of identities'); - - const sentHitsTracker4 = window.gaSpy.getHits('myTracker4'); - const sentHitsTracker5 = window.gaSpy.getHits('myTracker5'); - - t.equal(sentHitsTracker4.length, gaSendIterations, `Number of sent hits must be equal to the times 'send' command was invoked (${gaSendIterations})`); - t.equal(sentHitsTracker5.length, gaSendIterations, `Number of sent hits must be equal to the times 'send' command was invoked (${gaSendIterations})`); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - return 200; - }); - - gaTag(); - - window.ga('create', 'UA-00000004-1', 'example4.com', 'myTracker4', { siteSpeedSampleRate: 0 }); - window.ga('create', 'UA-00000005-1', 'example5.com', 'myTracker5', { siteSpeedSampleRate: 0 }); - - gaSpy(['myTracker4', 'myTracker5']); - - const factory = SplitFactory({ - ...config, - core: { key: config.core.key }, - integrations: [{ - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - identities: identitiesSdkOpts, - }], - }); - client = factory.client(); - - window.ga('myTracker4.require', 'splitTracker', { identities: identitiesPluginOpts }); - window.ga('myTracker5.require', 'splitTracker'); - - for (let i = 0; i < gaSendIterations; i++) { - window.ga('myTracker4.send', 'pageview'); - window.ga('myTracker5.send', 'event', 'mycategory', 'myaction'); - } - - }); - - // test custom filter and mapper in multiple trackers, passed as plugin options for one tracker and as sdk options for another - assert.test(t => { - const gaSendIterations = 3; - const prefixPluginOpts = 'plugin'; - const prefixSdkOpts = 'sdk'; - - let client; - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - t.equal(resp.length, gaSendIterations * 2, 'The number of sent Split events must be equal to the number of no filtered sent hits'); - t.equal(resp.filter(event => event.eventTypeId === prefixSdkOpts + '.mapperSdkOpts').length, gaSendIterations, 'Custom Split events'); - t.equal(resp.filter(event => event.eventTypeId === prefixPluginOpts + '.mapperPluginOpts').length, gaSendIterations, 'Custom Split events'); - - const sentHitsTracker4 = window.gaSpy.getHits('myTracker4'); - const sentHitsTracker5 = window.gaSpy.getHits('myTracker5'); - - t.equal(sentHitsTracker4.length, gaSendIterations * 2, 'Number of sent hits must be equal to the times `send` command was invoked'); - t.equal(sentHitsTracker5.length, gaSendIterations * 2, 'Number of sent hits must be equal to the times `send` command was invoked'); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - return 200; - }); - - gaTag(); - - window.ga('create', 'UA-00000004-1', 'example4.com', 'myTracker4', { siteSpeedSampleRate: 0 }); - window.ga('create', 'UA-00000005-1', 'example5.com', 'myTracker5', { siteSpeedSampleRate: 0 }); - - gaSpy(['myTracker4', 'myTracker5']); - - const factory = SplitFactory({ - ...config, - integrations: [{ - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - filter: model => model.get('hitType') === 'pageview', // accepts only pageviews - mapper: () => ({ eventTypeId: 'mapperSdkOpts' }), // return a fixed event instance - prefix: prefixSdkOpts, - }], - }); - client = factory.client(); - - window.ga('myTracker4.require', 'splitTracker', { - filter: model => model.get('hitType') === 'event', // accepts only events - mapper: (model, defaultEvent) => ({ ...defaultEvent, eventTypeId: 'mapperPluginOpts' }), // updates the eventTypeId of default event - prefix: prefixPluginOpts, - }); - window.ga('myTracker5.require', 'splitTracker'); - - for (let i = 0; i < gaSendIterations; i++) { - window.ga('myTracker4.send', 'pageview'); - window.ga('myTracker5.send', 'pageview'); - window.ga('myTracker4.send', 'event', 'mycategory', 'myaction'); - window.ga('myTracker5.send', 'event', 'mycategory', 'myaction'); - } - - }); - - // exception in custom mapper or invalid mapper result must not block sending hits - assert.test(t => { - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - t.equal(resp.length, 1, 'only a custom event is sent. no events associated to ga hit'); - return 200; - }); - - gaTag(); - - // siteSpeedSampleRate set to 0 to never send a site speed timing hit - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - window.ga('create', 'UA-00000001-1', 'example1.com', 'myTracker', { siteSpeedSampleRate: 0 }); - - gaSpy(['t0', 'myTracker']); - - window.ga('require', 'splitTracker', { mapper: function () { throw 'error'; } }); - // this second 'require' is not applied (it does not overwrite previous command) - window.ga('require', 'splitTracker'); - - window.ga('myTracker.require', 'splitTracker', { mapper: function () { return { value: 'invalid value' }; } }); - - const logSpy = sinon.spy(console, 'log'); - - window.ga('send', 'pageview'); - window.ga('myTracker.send', 'pageview'); - - const factory = SplitFactory(config); - factory.Logger.enable(); // Enable debug logs. Equivalent to `config.debug` true - client = factory.client(); - client.track('some_event'); - - setTimeout(() => { - const sentHitsT0 = window.gaSpy.getHits('t0'); - const sentHitsMyTracker = window.gaSpy.getHits('myTracker'); - t.equal(sentHitsT0.length, 1, 'Hits must be sent even if a custom mapper throw an exception'); - t.equal(sentHitsMyTracker.length, 1, 'Hits must be sent even if a custom mapper return an invalid event instance'); - t.ok(logSpy.calledWith('[ERROR] splitio => ga-to-split:mapper: value must be a finite number.')); - client.destroy(); - logSpy.restore(); - t.end(); - }); - - }); - - // test default behavior on default tracker: Split ready before GA init, and keep sending hits after Split destroyed - assert.test(t => { - const hits = [{ hitType: 'pageview' }, { hitType: 'event' }]; - const hitsAfterDestroyed = [{ hitType: 'screenview' }]; - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - const sentHits = window.gaSpy.getHits(); - - t.equal(resp.length, sentHits.length, `Number of sent hits must be equal to sent events (${hits.length})`); - t.equal(resp.length, hits.length, `Number of sent hits must be equal to sent events (${hits.length})`); - - setTimeout(() => { - client.destroy().then(() => { - hitsAfterDestroyed.forEach(hit => window.ga('send', hit)); - setTimeout(() => { - t.equal(sentHits.length, hits.length + hitsAfterDestroyed.length, 'sending hits must not be bloqued if Split SDK is destroyed'); - t.end(); - }); - }); - }); - return 200; - }); - - removeGaTag(); - - const factory = SplitFactory({ - ...config, - startup: { - eventsFirstPushWindow: 1000, - }, - scheduler: { - eventsQueueSize: hits.length, - } - }); - client = factory.client(); - - client.ready().then(() => { - addGaTag(); - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - gaSpy(); - - window.ga('require', 'splitTracker'); - hits.forEach(hit => window.ga('send', hit)); - - }); - }); - - // test `hits` flag - assert.test(t => { - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - const sentHits = window.gaSpy.getHits(); - - t.equal(resp.filter(event => event.eventTypeId === 'ga.pageview').length, 0, 'No events associated to GA hits must be sent'); - t.equal(resp.filter(event => event.eventTypeId === 'some_event').length, 1, 'Tracked events must be sent to Split'); - t.equal(sentHits.length, 1, 'Hits must be sent to GA'); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - return 200; - }); - - gaTag(); - - // siteSpeedSampleRate set to 0 to never send a site speed timing hit - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - - gaSpy(); - - window.ga('require', 'splitTracker', { hits: false }); - window.ga('send', 'pageview'); - - const factory = SplitFactory(config); - client = factory.client(); - client.track('some_event'); - - }); - - // test 'autoRequire' script placed right after GA script tag. - // We get same result if it is placed right before, and also applies for Universal Analytics configured with GTM and gtag.js tags. - // If it is executed asynchronously, trackers creation might be missed. - assert.test(t => { - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - const resp = JSON.parse(opts.body); - const sentHitsTracker1 = window.gaSpy.getHits('tracker1'); - const sentHitsTracker2 = window.gaSpy.getHits('tracker2'); - - t.equal(resp.length, sentHitsTracker1.length + sentHitsTracker2.length, 'All hits of all trackers are captured as Split events'); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - return 200; - }); - - gaTag(); - - // Run autoRequire iife: - // require('@splitsoftware/splitio-commons/src/integrations/ga/autoRequire'); - require('../../../scripts/ga-to-split-autorequire'); - - window.ga('create', 'UA-00000000-1', { name: 'tracker1', cookieDomain: 'auto', siteSpeedSampleRate: 0 }); - - gaSpy(['tracker1']); - - window.ga('tracker1.send', 'event', 'mycategory', 'myaction1'); // Captured - - const factory = SplitFactory({ - ...config, - integrations: [{ - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - autoRequire: true - }], - }); - - window.ga('tracker1.send', 'event', 'mycategory', 'myaction2'); // Captured - window.ga('create', 'UA-00000001-1', 'auto', 'tracker2', { siteSpeedSampleRate: 0 }); // New tracker - gaSpy(['tracker2'], false); - window.ga('tracker2.send', 'event', 'mycategory', 'myaction3'); // Captured - - client = factory.client(); - - }); - -} diff --git a/src/__tests__/gaIntegration/gaTestUtils.js b/src/__tests__/gaIntegration/gaTestUtils.js deleted file mode 100644 index e0aac43e3..000000000 --- a/src/__tests__/gaIntegration/gaTestUtils.js +++ /dev/null @@ -1,94 +0,0 @@ -export const DEFAULT_TRACKER = 't0'; - -const HIT_FIELDS = ['hitType', 'nonInteraction']; -const EVENT_FIELDS = ['eventCategory', 'eventAction', 'eventLabel', 'eventValue']; -const FIELDS = [...HIT_FIELDS, ...EVENT_FIELDS]; // List of hit fields to spy, which are the ones set by the default SplitToGa mapper. - -let hits = {}; - -/** - * Spy ga hits per tracker. - * - * @param {string[]} trackerNames names of the trackers to spy. If not provided, it spies the default tracker. i.e., `gaSpy()` is equivalent to `gaSpy(['t0'])`. - * @param {boolean} resetSpy true to reset the list of captured hits. - * - * @see {@link https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference} - */ -export function gaSpy(trackerNames = [DEFAULT_TRACKER], resetSpy = true) { - - if (resetSpy) hits = {}; - - // access ga via its gaAlias, accounting for the possibility that the global command queue - // has been renamed or not yet defined (analytics.js mutates window[gaAlias] reference) - const gaAlias = window['GoogleAnalyticsObject'] || 'ga'; - - if (typeof window[gaAlias] === 'function') { - window[gaAlias](function () { - // We try-catch the following code, since errors are catched by `ga` and thus cannot be traced for debugging. - try { - trackerNames.forEach(trackerName => { - const trackerToSniff = window[gaAlias].getByName(trackerName); - hits[trackerName] = []; - const originalSendHitTask = trackerToSniff.get('sendHitTask'); - trackerToSniff.set('sendHitTask', function (model) { - originalSendHitTask(model); - const hit = {}; - FIELDS.forEach(fieldName => { - hit[fieldName] = model.get(fieldName); - }); - hits[trackerName].push(hit); - }); - }); - } catch (err) { - console.log(err); - } - }); - } else { - console.error('GA command queue was not found'); - } - - window.gaSpy = { - // getHits may return `undefined` if `ga` is not ready or `trackerName` is not in the list of `trackerNames` - getHits: function (trackerName = DEFAULT_TRACKER) { - const trackerHits = hits[trackerName]; - return trackerHits; - } - }; - - return window.gaSpy; -} - -/** - * Add Google Analytics tag, removing previous one if exists. - * - * @see {@link https://developers.google.com/analytics/devguides/collection/analyticsjs#the_google_analytics_tag} - */ -export function gaTag(gaAlias = 'ga') { - removeGaTag(gaAlias); - addGaTag(gaAlias); -} - -/** - * Add Google Analytics tag. - */ -export function addGaTag(gaAlias = 'ga') { - (function (i, s, o, g, r, a, m) { - i['GoogleAnalyticsObject'] = r; - i[r] = i[r] || function () { - (i[r].q = i[r].q || []).push(arguments); - }, - i[r].l = 1 * new Date(); - a = s.createElement(o), - m = s.getElementsByTagName(o)[0]; - a.async = 1; - a.src = g; - m.parentNode.insertBefore(a, m); - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', gaAlias); -} - -/** - * Remove Google Analytics command queue. - */ -export function removeGaTag(gaAlias = 'ga') { - window[window['GoogleAnalyticsObject'] || gaAlias] = undefined; -} diff --git a/src/__tests__/gaIntegration/split-to-ga.spec.js b/src/__tests__/gaIntegration/split-to-ga.spec.js deleted file mode 100644 index 1285d6f01..000000000 --- a/src/__tests__/gaIntegration/split-to-ga.spec.js +++ /dev/null @@ -1,438 +0,0 @@ -import sinon from 'sinon'; -import { SplitFactory } from '../../'; -import { settingsFactory } from '../../settings'; -import { gaSpy, gaTag, removeGaTag, addGaTag } from './gaTestUtils'; -import { SPLIT_IMPRESSION, SPLIT_EVENT, DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; -import { url } from '../testUtils'; - -function countImpressions(parsedImpressionsBulkPayload) { - return parsedImpressionsBulkPayload - .reduce((accumulator, currentValue) => { return accumulator + currentValue.i.length; }, 0); -} - -const config = { - core: { - authorizationKey: '', - key: 'facundo@split.io', - trafficType: 'user', - }, - integrations: [{ - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - }], - scheduler: { - impressionsRefreshRate: 0.2, - eventsQueueSize: 1, - }, - streamingEnabled: false, - sync: { - impressionsMode: DEBUG, - } -}; - -const settings = settingsFactory(config); - -export default function (fetchMock, assert) { - - // test default behavior - assert.test(t => { - - let client; - - // Generator to synchronize the call of t.end() when both impressions and events endpoints were invoked. - const finish = (function* () { - yield; - t.equal(window.gaSpy.getHits().length, 3, 'Total hits are 3: pageview, split event and impression'); - setTimeout(() => { - client.destroy(); - t.end(); - }); - })(); - - fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, opts) => { - // we can assert payload and ga hits, once ga is ready and after `SplitToGa.queue`, that is timeout wrapped, make to the queue stack. - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentImpressions = countImpressions(resp); - const sentImpressionHits = window.gaSpy.getHits().filter(hit => hit.eventCategory === 'split-impression'); - - t.equal(sentImpressions, 1, 'Number of impressions'); - t.equal(sentImpressions, sentImpressionHits.length, `Number of sent impression hits must be equal to the number of impressions (${sentImpressions})`); - - finish.next(); - }); - }); - return 200; - }); - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentEvents = resp.length; - const sentEventHits = window.gaSpy.getHits().filter(hit => hit.eventCategory === 'split-event'); - - t.equal(sentEvents, 1, 'Number of events'); - t.equal(sentEvents, sentEventHits.length, `Number of sent event hits must be equal to sent events: (${sentEvents})`); - - finish.next(); - }); - }, 10); - return 200; - }); - - gaTag(); - - // siteSpeedSampleRate set to 0 to never send a site speed timing hit - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - - gaSpy(); - - window.ga('send', 'pageview'); - - const factory = SplitFactory(config); - client = factory.client(); - client.ready().then(() => { - client.track('some_event'); - client.getTreatment('hierarchical_splits_test'); - }); - - }); - - // test default behavior in multiple trackers, with multiple impressions, and GA in a different global variable - assert.test(t => { - - let client; - const numOfEvaluations = 4; - - fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, opts) => { - setTimeout(() => { - window.other_location_for_ga(() => { - const resp = JSON.parse(opts.body); - const sentImpressions = countImpressions(resp); - const sentHitsTracker1 = window.gaSpy.getHits('myTracker1'); - const sentHitsTracker2 = window.gaSpy.getHits('myTracker2'); - - t.equal(sentImpressions, numOfEvaluations, 'Number of impressions equals the number of evaluations'); - t.equal(sentImpressions, sentHitsTracker1.length, 'Number of sent hits must be equal to the number of impressions'); - t.equal(sentImpressions, sentHitsTracker2.length, 'Number of sent hits must be equal to the number of impressions'); - - setTimeout(() => { - client.destroy(); - t.end(); - }); - }); - }); - return 200; - }); - - gaTag('other_location_for_ga'); - - window.other_location_for_ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - window.other_location_for_ga('create', 'UA-00000001-1', 'example1.com', 'myTracker1', { siteSpeedSampleRate: 0 }); - window.other_location_for_ga('create', 'UA-00000002-1', 'example2.com', 'myTracker2', { siteSpeedSampleRate: 0 }); - - gaSpy(['myTracker1', 'myTracker2']); - - const factory = SplitFactory({ - ...config, - core: { - ...config.core, - authorizationKey: '', - }, - integrations: [{ - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - trackerNames: ['myTracker1'], - }, { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - trackerNames: ['myTracker2'], - }], - }); - client = factory.client(); - client.ready().then(() => { - for (let i = 0; i < numOfEvaluations; i++) - client.getTreatment('split_with_config'); - }); - - }); - - // test several SplitToGa integration items, with custom filter and mapper - assert.test(t => { - - let client; - const numOfEvaluations = 4; - const numOfEvents = 3; - - // Generator to synchronize the call of t.end() when both impressions and events endpoints were invoked. - const finish = (function* () { - yield; - setTimeout(() => { - client.destroy(); - t.end(); - }); - })(); - - fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, opts) => { - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentImpressions = countImpressions(resp); - const sentImpressionHitsTracker3 = window.gaSpy.getHits('myTracker3').filter(hit => hit.eventCategory === 'split-impression'); - const sentImpressionHitsTracker4 = window.gaSpy.getHits('myTracker4').filter(hit => hit.eventCategory === 'split-impression'); - - t.equal(sentImpressionHitsTracker3.length, sentImpressions, 'For tracker3, no impressions are filtered'); - t.equal(sentImpressionHitsTracker4.length, 0, 'For tracker4, all impressions are filtered'); - - finish.next(); - }); - }); - return 200; - }); - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentEvents = resp.length; - const sentEventHitsTracker3 = window.gaSpy.getHits('myTracker3').filter(hit => hit.eventCategory === 'mycategory'); - const sentEventHitsTracker4 = window.gaSpy.getHits('myTracker4').filter(hit => hit.eventCategory === 'mycategory'); - - t.equal(sentEventHitsTracker3.length, 0, 'For tracker3, all events are filtered'); - t.equal(sentEventHitsTracker4.length, sentEvents, 'For tracker4, no events are filtered'); - - finish.next(); - }); - }, 10); - return 200; - }); - - gaTag(); - - window.ga('create', 'UA-00000003-1', 'example3.com', 'myTracker3', { siteSpeedSampleRate: 0 }); - window.ga('create', 'UA-00000004-1', 'example4.com', 'myTracker4', { siteSpeedSampleRate: 0 }); - - gaSpy(['myTracker3', 'myTracker4']); - - const onlyImpressionsFilter = ({ type }) => type === SPLIT_IMPRESSION; - const onlyEventsMapper = function ({ payload, type }) { - return type === SPLIT_EVENT ? - { hitType: 'event', eventCategory: 'mycategory', eventAction: payload.eventTypeId } : - undefined; - }; - const factory = SplitFactory({ - ...config, - core: { - ...config.core, - authorizationKey: '', - }, - scheduler: { - impressionsRefreshRate: 0.2, - eventsQueueSize: numOfEvents, - }, - integrations: [{ - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - trackerNames: ['myTracker3'], - filter: onlyImpressionsFilter, - }, { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - trackerNames: ['myTracker4'], - mapper: onlyEventsMapper, - }], - }); - client = factory.client(); - client.ready().then(() => { - for (let i = 0; i < numOfEvaluations; i++) { - client.getTreatment('split_with_config'); - } - for (let i = 0; i < numOfEvents; i++) { - client.track('eventType'); - } - }); - - }); - - // exception in custom mapper or invalid mapper result must not send a hit - assert.test(t => { - - const logSpy = sinon.spy(console, 'log'); - const error = 'some error'; - let client; - const numOfEvaluations = 1; - - fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, opts) => { - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentImpressions = countImpressions(resp); - const sentHitsDefault = window.gaSpy.getHits(); - const sentHitsTracker1 = window.gaSpy.getHits('myTracker1'); - const sentHitsTracker2 = window.gaSpy.getHits('myTracker2'); - - t.equal(sentImpressions, numOfEvaluations, 'Number of impressions equals the number of evaluations'); - t.equal(sentHitsDefault.length, 0, 'No hits sent if custom mapper throws error'); - t.equal(sentHitsTracker1.length, 0, 'No hits sent if custom mapper returns invalid result'); - t.equal(sentHitsTracker2.length, numOfEvaluations, 'Number of sent hits must be equal to the number of impressions'); - - setTimeout(() => { - t.ok(logSpy.calledWith(`[WARN] splitio => split-to-ga: queue method threw: ${error}. No hit was sent.`)); - t.ok(logSpy.calledWith('[WARN] splitio => split-to-ga: your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.')); - client.destroy(); - logSpy.restore(); - t.end(); - }); - }); - }); - return 200; - }); - - gaTag(); - - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - window.ga('create', 'UA-00000001-1', 'example1.com', 'myTracker1', { siteSpeedSampleRate: 0 }); - window.ga('create', 'UA-00000002-1', 'example2.com', 'myTracker2', { siteSpeedSampleRate: 0 }); - - gaSpy(['t0', 'myTracker1', 'myTracker2']); - - const factory = SplitFactory({ - ...config, - debug: true, - integrations: [{ - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - mapper: function () { throw error; }, - }, { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - trackerNames: ['myTracker1'], - mapper: function () { return {}; }, - }, { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - trackerNames: ['myTracker2'], - mapper: function () { return { hitType: 'event', eventCategory: 'my-split-impression', eventAction: 'some-action' }; }, - }], - }); - client = factory.client(); - client.ready().then(() => { - for (let i = 0; i < numOfEvaluations; i++) - client.getTreatment('split_with_config'); - }); - - }); - - // Split created before GA initialized - assert.test(t => { - - const logSpy = sinon.spy(console, 'log'); - let client; - const numOfEvaluations = 1; - - fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, opts) => { - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentImpressions = countImpressions(resp); - const sentHitsDefault = window.gaSpy.getHits(); - - t.equal(sentImpressions, numOfEvaluations, 'Number of impressions equals the number of evaluations'); - t.equal(sentHitsDefault.length, numOfEvaluations, 'Hits sent if ga initialized before Split evaluation (client.getTreatment***)'); - - setTimeout(() => { - client.destroy().then(() => { - logSpy.restore(); - t.end(); - }); - }); - }); - }); - return 200; - }); - - removeGaTag(); - - const factory = SplitFactory({ - ...config, - debug: true, - }); - t.ok(logSpy.calledWith('[WARN] splitio => split-to-ga: `ga` command queue not found. No hits will be sent until it is available.'), 'warning GA not found'); - - client = factory.client(); - client.ready().then(() => { - for (let i = 0; i < numOfEvaluations; i++) - client.getTreatment('split_with_config'); - }); - - addGaTag(); - - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - - gaSpy(); - - }); - - // test `events` and `impressions` flags - assert.test(t => { - - let client; - - // Generator to synchronize the call of t.end() when both impressions and events endpoints were invoked. - const finish = (function* () { - yield; - t.equal(window.gaSpy.getHits().length, 1, 'Total hits are 1: pageview'); - setTimeout(() => { - client.destroy(); - t.end(); - }); - })(); - - fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, opts) => { - // we can assert payload and ga hits, once ga is ready and after `SplitToGa.queue`, that is timeout wrapped, make to the queue stack. - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentImpressions = countImpressions(resp); - const sentImpressionHits = window.gaSpy.getHits().filter(hit => hit.eventCategory === 'split-impression'); - - t.equal(sentImpressions, 1, 'Number of impressions'); - t.equal(sentImpressionHits.length, 0, 'No hits associated to Split impressions must be sent'); - - finish.next(); - }); - }); - return 200; - }); - - fetchMock.postOnce(url(settings, '/events/bulk'), (url, opts) => { - setTimeout(() => { - window.ga(() => { - const resp = JSON.parse(opts.body); - const sentEvents = resp.length; - const sentEventHits = window.gaSpy.getHits().filter(hit => hit.eventCategory === 'split-event'); - - t.equal(sentEvents, 1, 'Number of events'); - t.equal(sentEventHits.length, 0, 'No hits associated to Split events must be sent'); - - finish.next(); - }); - }); - return 200; - }); - - gaTag(); - window.ga('create', 'UA-00000000-1', 'auto', { siteSpeedSampleRate: 0 }); - gaSpy(); - window.ga('send', 'pageview'); - - const factory = SplitFactory({ - ...config, - integrations: [{ - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - events: false, - impressions: false, - }] - }); - client = factory.client(); - client.ready().then(() => { - client.track('some_event'); - client.getTreatment('hierarchical_splits_test'); - }); - - }); -} diff --git a/src/__tests__/online/browser.spec.js b/src/__tests__/online/browser.spec.js index e3c6ebe86..05fd60de2 100644 --- a/src/__tests__/online/browser.spec.js +++ b/src/__tests__/online/browser.spec.js @@ -10,7 +10,7 @@ import telemetrySuite from '../browserSuites/telemetry.spec'; import impressionsListenerSuite from '../browserSuites/impressions-listener.spec'; import readinessSuite from '../browserSuites/readiness.spec'; import readyFromCache from '../browserSuites/ready-from-cache.spec'; -import { withoutBindingTT, bindingTT } from '../browserSuites/events.spec'; +import { withoutBindingTT } from '../browserSuites/events.spec'; import sharedInstantiationSuite from '../browserSuites/shared-instantiation.spec'; import managerSuite from '../browserSuites/manager.spec'; import ignoreIpAddressesSettingSuite from '../browserSuites/ignore-ip-addresses-setting.spec'; @@ -112,10 +112,8 @@ tape('## E2E CI Tests ##', function (assert) { assert.test('E2E / Telemetry', telemetrySuite.bind(null, fetchMock)); /* Check events */ assert.test('E2E / Events', withoutBindingTT.bind(null, fetchMock)); - assert.test('E2E / Events with TT bound', bindingTT.bind(null, fetchMock)); /* Check shared clients */ - assert.test('E2E / Shared instances', sharedInstantiationSuite.bind(null, false, false, fetchMock)); - assert.test('E2E / Shared instances with Traffic Type on factory settings', sharedInstantiationSuite.bind(null, true, false, fetchMock)); + assert.test('E2E / Shared instances', sharedInstantiationSuite.bind(null, false, true, fetchMock)); /* Validate user consent */ assert.test('E2E / User consent', userConsent.bind(null, fetchMock)); /* Check basic manager functionality */ @@ -127,7 +125,7 @@ tape('## E2E CI Tests ##', function (assert) { /* Check that impressions and events are sended to backend via Beacon API or Fetch when pagehide/visibilitychange events are triggered. */ assert.test('E2E / Use Beacon API (or Fetch if not available) to send remaining impressions and events when browser page is unload or hidden', useBeaconApiSuite.bind(null, fetchMock)); assert.test('E2E / Use Beacon API DEBUG (or Fetch if not available) to send remaining impressions and events when browser page is unload or hidden', useBeaconDebugApiSuite.bind(null, fetchMock)); - /* Validate ready from cache behaviour (might be merged into another suite if we end up having simple behavior around it as expected) */ + /* Validate ready from cache behavior (might be merged into another suite if we end up having simple behavior around it as expected) */ assert.test('E2E / Readiness from cache', readyFromCache.bind(null, fetchMock)); /* Validate readiness with ready promises */ assert.test('E2E / Ready promise', readyPromiseSuite.bind(null, fetchMock)); diff --git a/src/__tests__/testUtils/index.js b/src/__tests__/testUtils/index.js index 7f01fc5e4..5994a3c30 100644 --- a/src/__tests__/testUtils/index.js +++ b/src/__tests__/testUtils/index.js @@ -14,7 +14,7 @@ export function nearlyEqual(actual, expected, epsilon = DEFAULT_ERROR_MARGIN) { } /** - * mock the basic behaviour for `/segmentChanges` endpoint: + * mock the basic behavior for `/segmentChanges` endpoint: * - when `?since=-1`, it returns the given segment `keys` in `added` list. * - otherwise, it returns empty `added` and `removed` lists, and the same since and till values. * diff --git a/src/factory/browser.js b/src/factory/browser.js index 9b877a36d..b06eac524 100644 --- a/src/factory/browser.js +++ b/src/factory/browser.js @@ -5,9 +5,8 @@ import { pollingManagerCSFactory } from '@splitsoftware/splitio-commons/src/sync import { InLocalStorage } from '@splitsoftware/splitio-commons/src/storages/inLocalStorage'; import { InMemoryStorageCSFactory } from '@splitsoftware/splitio-commons/src/storages/inMemory/InMemoryStorageCS'; import { sdkManagerFactory } from '@splitsoftware/splitio-commons/src/sdkManager'; -import { sdkClientMethodCSFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethodCSWithTT'; +import { sdkClientMethodCSFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethodCS'; import { impressionObserverCSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverCS'; -import { integrationsManagerFactory } from '@splitsoftware/splitio-commons/src/integrations/browser'; import { __InLocalStorageMockFactory } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/storage/storageCS'; import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory'; import { LOCALHOST_MODE, STORAGE_LOCALSTORAGE } from '@splitsoftware/splitio-commons/src/utils/constants'; @@ -49,8 +48,6 @@ function getModules(settings) { SignalListener, - integrationsManagerFactory: settings.integrations && settings.integrations.length > 0 ? integrationsManagerFactory.bind(null, settings.integrations) : undefined, - impressionsObserverFactory: impressionObserverCSFactory, extraProps: (params) => { diff --git a/src/settings/__tests__/browser.spec.js b/src/settings/__tests__/browser.spec.js index 0a37e0772..481b9e95e 100644 --- a/src/settings/__tests__/browser.spec.js +++ b/src/settings/__tests__/browser.spec.js @@ -1,36 +1,6 @@ import tape from 'tape-catch'; import { settingsFactory } from '../browser'; -tape('SETTINGS / Integrations should be properly parsed', assert => { - const settings = settingsFactory({ - core: { - authorizationKey: 'dummy token' - }, - integrations: [ - { type: 'GOOGLE_ANALYTICS_TO_SPLIT', prefix: 'prefix1' }, - { type: 'INVALID_INTEGRATION', prefix: 'prefix2' }, - { type: 'SPLIT_TO_GOOGLE_ANALYTICS', prefix: 'prefix3' }, - { type: 'INVALID_INTEGRATION_2', prefix: 'prefix4' }, - {}, - 'INVALID' - ] - }); - - assert.deepEqual(settings.integrations, [ - { type: 'GOOGLE_ANALYTICS_TO_SPLIT', prefix: 'prefix1' }, - { type: 'SPLIT_TO_GOOGLE_ANALYTICS', prefix: 'prefix3' } - ], 'Filters invalid integrations from `integrations` array'); - - assert.deepEqual(settingsFactory({ - core: { - authorizationKey: 'dummy token' - }, - integrations: 'INVALID' - }).integrations, [], 'Returns an empty array if `integrations` is an invalid object'); - - assert.end(); -}); - tape('SETTINGS / Consent is overwritable and "GRANTED" by default in client-side', assert => { let settings = settingsFactory({}); assert.equal(settings.userConsent, 'GRANTED', 'userConsent defaults to granted if not provided.'); diff --git a/src/settings/browser.js b/src/settings/browser.js index d3f04443e..5a1ae432b 100644 --- a/src/settings/browser.js +++ b/src/settings/browser.js @@ -6,14 +6,12 @@ import { validateConsent } from '@splitsoftware/splitio-commons/src/utils/settin import { defaults } from './defaults/browser'; import { validateStorage } from './storage/browser'; -import { validateIntegrations } from './integrations/browser'; const params = { defaults, - acceptKey: true, acceptTT: true, // Client with bound key and optional TT + acceptKey: true, // Client with bound key runtime: validateRuntime, storage: validateStorage, - integrations: validateIntegrations, logger: validateLogger, localhost: () => LocalhostFromObject(), consent: validateConsent, diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 1e30feddf..7f7b63b6a 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '10.28.1-rc.2'; +export const packageVersion = '11.0.0-rc.0'; diff --git a/src/sync/offline/splitsParserFromFile.js b/src/sync/offline/splitsParserFromFile.js index aef992544..13f2f1c29 100644 --- a/src/sync/offline/splitsParserFromFile.js +++ b/src/sync/offline/splitsParserFromFile.js @@ -31,7 +31,7 @@ function configFilesPath(configFilePath) { } // This function is not pure nor meant to be. Here we apply modifications to cover -// for behaviour that's ensured by the BE. +// for behavior that's ensured by the BE. function arrangeConditions(mocksData) { // Iterate through each feature flag data forOwn(mocksData, data => { diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 7bdc4c834..2440be58a 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -163,7 +163,6 @@ browserSettings = { } }; // With sync settings should return ISDK, if settings have async storage it should return IAsyncSDK -SDK = SplitFactory(browserSettings); SDK = SplitFactory(nodeSettings); AsyncSDK = SplitFactory(asyncSettings); BrowserSDK = SplitFactory(browserSettings); @@ -172,7 +171,6 @@ BrowserSDK = SplitFactory(browserSettings); const instantiatedSettingsCore: { authorizationKey: string, key: SplitIO.SplitKey, - trafficType: string, labelsEnabled: boolean, IPAddressesEnabled: boolean } = SDK.settings.core; @@ -195,9 +193,8 @@ SDK.settings.features = { 'split_x': 'on' }; // Browser // Client and Manager client = SDK.client(); -client = SDK.client('a customer key'); -client = SDK.client('a customer key', 'a traffic type'); manager = SDK.manager(); +manager = BrowserSDK.manager(); // Today async clients are only possible on Node. Shared client creation not available here. asyncClient = AsyncSDK.client(); asyncManager = AsyncSDK.manager(); @@ -248,72 +245,69 @@ promise = SDK.destroy(); // We can call getTreatment with or without a key. treatment = client.getTreatment(splitKey, 'mySplit'); -treatment = client.getTreatment('mySplit'); +treatment = browserClient.getTreatment('mySplit'); // Attributes parameter is optional on both signatures. treatment = client.getTreatment(splitKey, 'mySplit', attributes); -treatment = client.getTreatment('mySplit', attributes); +treatment = browserClient.getTreatment('mySplit', attributes); // We can call getTreatments with or without a key. treatments = client.getTreatments(splitKey, ['mySplit']); -treatments = client.getTreatments(['mySplit']); +treatments = browserClient.getTreatments(['mySplit']); // Attributes parameter is optional on both signatures. treatments = client.getTreatments(splitKey, ['mySplit'], attributes); -treatments = client.getTreatments(['mySplit'], attributes); +treatments = browserClient.getTreatments(['mySplit'], attributes); // We can call getTreatmentWithConfig with or without a key. treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit'); -treatmentWithConfig = client.getTreatmentWithConfig('mySplit'); +treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit'); // Attributes parameter is optional on both signatures. treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit', attributes); -treatmentWithConfig = client.getTreatmentWithConfig('mySplit', attributes); +treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit', attributes); // We can call getTreatmentsWithConfig with or without a key. treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit']); -treatmentsWithConfig = client.getTreatmentsWithConfig(['mySplit']); +treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit']); // Attributes parameter is optional on both signatures. treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); -treatmentsWithConfig = client.getTreatmentsWithConfig(['mySplit'], attributes); +treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit'], attributes); -// We can call getTreatmentsByFlagSet without a key. +// We can call getTreatmentsByFlagSet with or without a key. treatments = client.getTreatmentsByFlagSet(splitKey, 'set_a'); -treatments = client.getTreatmentsByFlagSet('set_a'); +treatments = browserClient.getTreatmentsByFlagSet('set_a'); // Attributes parameter is optional. treatments = client.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); -treatments = client.getTreatmentsByFlagSet('set_a', attributes); +treatments = browserClient.getTreatmentsByFlagSet('set_a', attributes); -// We can call getTreatmentsByFlagSets without a key. +// We can call getTreatmentsByFlagSets with or without a key. treatments = client.getTreatmentsByFlagSets(splitKey, ['set_a']); -treatments = client.getTreatmentsByFlagSets(['set_a']); +treatments = browserClient.getTreatmentsByFlagSets(['set_a']); // Attributes parameter is optional. treatments = client.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); -treatments = client.getTreatmentsByFlagSets(['set_a'], attributes); +treatments = browserClient.getTreatmentsByFlagSets(['set_a'], attributes); -// We can call getTreatmentsWithConfigByFlagSet without a key. +// We can call getTreatmentsWithConfigByFlagSet with or without a key. treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet('set_a'); +treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSet('set_a'); // Attributes parameter is optional. treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet('set_a', attributes); +treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSet('set_a', attributes); -// We can call getTreatmentsWithConfigByFlagSets without a key. +// We can call getTreatmentsWithConfigByFlagSets with or without a key. treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(['set_a']); +treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSets(['set_a']); // Attributes parameter is optional. treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(['set_a'], attributes); +treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSets(['set_a'], attributes); -// We can call track with or without a key. Traffic type can also be bound to the client. +// We can call track with or without a key. tracked = client.track(splitKey, 'myTrafficType', 'myEventType'); // all params -tracked = client.track('myTrafficType', 'myEventType'); // key bound, tt provided. -tracked = client.track('myEventType'); // key and tt bound. +tracked = browserClient.track('myTrafficType', 'myEventType'); // key bound, tt provided. // Value parameter is optional on all signatures. tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10); -tracked = client.track('myTrafficType', 'myEventType', 10); -tracked = client.track('myEventType', 10); +tracked = browserClient.track('myTrafficType', 'myEventType', 10); // Properties parameter is optional on all signatures. tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); -tracked = client.track('myTrafficType', 'myEventType', null, { prop1: 1, prop2: '2', prop3: false, prop4: null }); -tracked = client.track('myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); +tracked = browserClient.track('myTrafficType', 'myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); /*** Repeating tests for Async Client ***/ @@ -494,40 +488,10 @@ userConsent = BrowserSDK.UserConsent.Status.UNKNOWN; // Split filters let splitFilters: SplitIO.SplitFilter[] = [{ type: 'bySet', values: ['set_a', 'set_b'] }, { type: 'byName', values: ['my_split_1', 'my_split_1'] }, { type: 'byPrefix', values: ['my_split', 'test_split_'] }] -// Browser integrations -let fieldsObjectSample: UniversalAnalytics.FieldsObject = { hitType: 'event', eventAction: 'action' }; -let eventDataSample: SplitIO.EventData = { eventTypeId: 'someEventTypeId', value: 10, properties: {} } - -let googleAnalyticsToSplitConfig: SplitIO.IGoogleAnalyticsToSplitConfig = { - type: 'GOOGLE_ANALYTICS_TO_SPLIT', -}; -let splitToGoogleAnalyticsConfig: SplitIO.ISplitToGoogleAnalyticsConfig = { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', -}; - -let customGoogleAnalyticsToSplitConfig: SplitIO.IGoogleAnalyticsToSplitConfig = { - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - hits: false, - filter: function (model: UniversalAnalytics.Model): boolean { return true; }, - mapper: function (model: UniversalAnalytics.Model, defaultMapping: SplitIO.EventData): SplitIO.EventData { return eventDataSample; }, - prefix: 'PREFIX', - identities: [{ key: 'key1', trafficType: 'tt1' }, { key: 'key2', trafficType: 'tt2' }], - autoRequire: true -}; -let customSplitToGoogleAnalyticsConfig: SplitIO.ISplitToGoogleAnalyticsConfig = { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - events: false, - impressions: true, - filter: function (model: SplitIO.IntegrationData): boolean { return true; }, - mapper: function (model: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject): UniversalAnalytics.FieldsObject { return fieldsObjectSample; }, - trackerNames: ['t0', 'myTracker'], -} - let fullBrowserSettings: SplitIO.IBrowserSettings = { core: { authorizationKey: 'asd', key: 'asd', - trafficType: 'myTT', labelsEnabled: false }, scheduler: { @@ -562,7 +526,6 @@ let fullBrowserSettings: SplitIO.IBrowserSettings = { }, impressionListener: impressionListener, debug: true, - integrations: [googleAnalyticsToSplitConfig, splitToGoogleAnalyticsConfig, customGoogleAnalyticsToSplitConfig, customSplitToGoogleAnalyticsConfig], streamingEnabled: true, sync: { splitFilters: splitFilters, @@ -575,7 +538,6 @@ let fullBrowserSettings: SplitIO.IBrowserSettings = { userConsent: 'GRANTED' }; fullBrowserSettings.storage.type = 'MEMORY'; -fullBrowserSettings.integrations[0].type = 'GOOGLE_ANALYTICS_TO_SPLIT'; fullBrowserSettings.userConsent = 'DECLINED'; fullBrowserSettings.userConsent = 'UNKNOWN'; diff --git a/types/client/index.d.ts b/types/client/index.d.ts index d94090d91..ba6d4a9d4 100644 --- a/types/client/index.d.ts +++ b/types/client/index.d.ts @@ -6,7 +6,7 @@ export = JsSdk; declare module JsSdk { /** - * Split.io sdk factory function. + * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.IBrowserSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration} */ diff --git a/types/index.d.ts b/types/index.d.ts index 78c5d824f..adaf540dd 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -8,19 +8,19 @@ export = JsSdk; declare module JsSdk { /** - * Split.io sdk factory function. + * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeAsyncSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.IAsyncSDK; /** - * Split.io sdk factory function. + * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.ISDK; /** - * Split.io sdk factory function. + * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.IBrowserSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration} */ diff --git a/types/server/index.d.ts b/types/server/index.d.ts index a9a145a2f..f39f44bf6 100644 --- a/types/server/index.d.ts +++ b/types/server/index.d.ts @@ -6,13 +6,13 @@ export = JsSdk; declare module JsSdk { /** - * Split.io sdk factory function. + * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeAsyncSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.IAsyncSDK; /** - * Split.io sdk factory function. + * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ diff --git a/types/splitio.d.ts b/types/splitio.d.ts index e5fc78c28..7abd18d7c 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -2,7 +2,6 @@ // Project: http://www.split.io/ // Definitions by: Nico Zelaya -/// import { RedisOptions } from "ioredis"; import { RequestOptions } from "http"; @@ -63,7 +62,6 @@ interface ISettings { readonly core: { authorizationKey: string, key: SplitIO.SplitKey, - trafficType: string, labelsEnabled: boolean, IPAddressesEnabled: boolean }, @@ -354,7 +352,7 @@ interface INodeBasicSettings extends ISharedSettings { 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} + * For more information see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#localhost-mode} * @property {number} offlineRefreshRate * @default 15 */ @@ -373,7 +371,8 @@ interface INodeBasicSettings extends ISharedSettings { */ core: { /** - * Your SDK key. More information: @see {@link https://help.split.io/hc/en-us/articles/360019916211-API-keys} + * Your SDK key. + * @see {@link https://help.split.io/hc/en-us/articles/360019916211-API-keys} * @property {string} authorizationKey */ authorizationKey: string, @@ -421,7 +420,7 @@ interface INodeBasicSettings extends ISharedSettings { */ mode?: SDKMode, /** - * Mocked features file path. For testing purposses only. For using this you should specify "localhost" as authorizationKey on core settings. + * Mocked features file path. For testing purposes 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' @@ -440,20 +439,9 @@ interface IStatusInterface extends EventEmitter { */ Event: EventConsts, /** - * Returns a promise that resolves 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 - * } - * ``` + * Returns a promise that resolves 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, the `ready` method will return a resolved promise once the SDK is ready. + * You must handle the promise rejection to avoid an unhandled promise rejection error, or you can set the `startup.readyTimeout` configuration option to 0 to avoid the timeout and thus the rejection. * * @function ready * @returns {Promise} @@ -500,9 +488,8 @@ interface IBasicSDK { } /****** 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} + * Types and interfaces for `@splitsoftware/splitio` package for usage when integrating JavaScript SDK with TypeScript. + * For the SDK package information see {@link https://www.npmjs.com/package/@splitsoftware/splitio} */ declare namespace SplitIO { /** @@ -732,154 +719,6 @@ declare namespace SplitIO { interface IImpressionListener { logImpression(data: SplitIO.ImpressionData): void } - /** - * A pair of user key and it's trafficType, required for tracking valid Split events. - * @typedef {Object} Identity - * @property {string} key The user key. - * @property {string} trafficType The key traffic type. - */ - type Identity = { - key: string; - trafficType: string; - }; - /** - * Object with information about a Split event. - * @typedef {Object} EventData - */ - type EventData = { - eventTypeId: string; - value?: number; - properties?: Properties; - trafficTypeName?: string; - key?: string; - timestamp?: number; - }; - /** - * Enable 'Google Analytics to Split' integration, to track Google Analytics hits as Split events. - * - * @see {@link https://help.split.io/hc/en-us/articles/360040838752#google-analytics-to-split} - */ - interface IGoogleAnalyticsToSplitConfig { - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - /** - * Optional flag to filter GA hits from being tracked as Split events. - * @property {boolean} hits - * @default true - */ - hits?: boolean, - /** - * Optional predicate used to define a custom filter for tracking GA hits as Split events. - * For example, the following filter allows to track only 'event' hits: - * `(model) => model.get('hitType') === 'event'` - * By default, all hits are tracked as Split events. - */ - filter?: (model: UniversalAnalytics.Model) => boolean, - /** - * Optional function useful when you need to modify the Split event before tracking it. - * This function is invoked with two arguments: - * 1. the GA model object representing the hit. - * 2. the default format of the mapped Split event instance. - * The return value must be a Split event, that can be the second argument or a new object. - * - * For example, the following mapper adds a custom property to events: - * `(model, defaultMapping) => { - * defaultMapping.properties.someProperty = SOME_VALUE; - * return defaultMapping; - * }` - */ - mapper?: (model: UniversalAnalytics.Model, defaultMapping: SplitIO.EventData) => SplitIO.EventData, - /** - * Optional prefix for EventTypeId, to prevent any kind of data collision between events. - * @property {string} prefix - * @default 'ga' - */ - prefix?: string, - /** - * List of Split identities (key & traffic type pairs) used to track events. - * If not provided, events are sent using the key and traffic type provided at SDK config - */ - identities?: Identity[], - /** - * Optional flag to log an error if the `auto-require` script is not detected. - * The auto-require script automatically requires the `splitTracker` plugin for created trackers, - * and should be placed right after your Google Analytics, Google Tag Manager or gtag.js script tag. - * - * @see {@link https://help.split.io/hc/en-us/articles/360040838752#set-up-with-gtm-and-gtag.js} - * - * @property {boolean} autoRequire - * @default false - */ - autoRequire?: boolean, - } - /** - * 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. - */ - type IntegrationData = { type: 'IMPRESSION', payload: SplitIO.ImpressionData } | { type: 'EVENT', payload: SplitIO.EventData }; - /** - * Enable 'Split to Google Analytics' integration, to track Split impressions and events as Google Analytics hits. - * - * @see {@link https://help.split.io/hc/en-us/articles/360040838752#split-to-google-analytics} - */ - interface ISplitToGoogleAnalyticsConfig { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - /** - * Optional flag to filter Split impressions from being tracked as GA hits. - * @property {boolean} impressions - * @default true - */ - impressions?: boolean, - /** - * Optional flag to filter Split events from being tracked as GA hits. - * @property {boolean} events - * @default true - */ - events?: boolean, - /** - * Optional predicate used to define a custom filter for tracking Split data (events and impressions) as GA hits. - * 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, - /** - * Optional function useful when you need to modify the GA hit before sending it. - * This function is invoked with two arguments: - * 1. the input data (Split event or impression). - * 2. the default format of the mapped FieldsObject instance (GA hit). - * The return value must be a FieldsObject, that can be the second argument or a new object. - * - * For example, the following mapper adds a custom dimension to hits: - * `(data, defaultMapping) => { - * defaultMapping.dimension1 = SOME_VALUE; - * return defaultMapping; - * }` - * - * Default FieldsObject instance for data.type === 'IMPRESSION': - * `{ - * hitType: 'event', - * eventCategory: 'split-impression', - * eventAction: 'Evaluate ' + data.payload.impression.feature, - * eventLabel: 'Treatment: ' + data.payload.impression.treatment + '. Targeting rule: ' + data.payload.impression.label + '.', - * nonInteraction: true, - * }` - * Default FieldsObject instance for data.type === 'EVENT': - * `{ - * hitType: 'event', - * eventCategory: 'split-event', - * eventAction: data.payload.eventTypeId, - * eventValue: data.payload.value, - * nonInteraction: true, - * }` - */ - mapper?: (data: SplitIO.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. - */ - trackerNames?: string[], - } /** * Available URL settings for the SDKs. */ @@ -916,10 +755,6 @@ declare namespace SplitIO { telemetry?: string }; - /** - * Available integration options for the browser - */ - type BrowserIntegration = ISplitToGoogleAnalyticsConfig | IGoogleAnalyticsToSplitConfig; /** * SplitFilter type. * @@ -1050,7 +885,7 @@ declare namespace SplitIO { 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/360020448791-JavaScript-SDK#localhost-mode} + * For more information see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#localhost-mode} * @property {number} offlineRefreshRate * @default 15 */ @@ -1069,21 +904,17 @@ declare namespace SplitIO { */ core: { /** - * Your SDK key. More information: @see {@link https://help.split.io/hc/en-us/articles/360019916211-API-keys} + * Your SDK key. + * @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} + * 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 @@ -1092,7 +923,7 @@ declare namespace SplitIO { labelsEnabled?: boolean }, /** - * Mocked features map. For testing purposses only. For using this you should specify "localhost" as authorizationKey on core settings. + * Mocked features map. For testing purposes 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?: MockedFeaturesMap, @@ -1121,11 +952,6 @@ declare namespace SplitIO { * @property {Object} urls */ urls?: UrlSettings, - /** - * SDK integration settings for the Browser. - * @property {Object} integrations - */ - integrations?: BrowserIntegration[], /** * User consent status. Possible values are `'GRANTED'`, which is the default, `'DECLINED'` or `'UNKNOWN'`. * - `'GRANTED'`: the user grants consent for tracking events and impressions. The SDK sends them to Split cloud. @@ -1380,14 +1206,6 @@ declare namespace SplitIO { * @returns {IClient} The client instance. */ client(): IClient, - /** - * Returns a shared client of the SDK. For usage on the browser. - * @function client - * @param {SplitKey} key The key for the new client instance. - * @param {string=} trafficType The traffic type of the provided key. - * @returns {IClient} The client instance. - */ - client(key: SplitKey, trafficType?: string): IClient, /** * Returns a manager instance of the SDK to explore available information. * @function manager @@ -1398,9 +1216,9 @@ declare namespace SplitIO { /** * This represents the interface for the SDK instance with synchronous storage. * @interface IBrowserSDK - * @extends ISDK + * @extends IBasicSDK */ - interface IBrowserSDK extends ISDK { + interface IBrowserSDK extends IBasicSDK { /** * Returns the default client instance of the SDK. * @function client @@ -1408,13 +1226,18 @@ declare namespace SplitIO { */ client(): IBrowserClient, /** - * Returns a shared client of the SDK. For usage on the browser. + * Returns a shared client of the SDK. * @function client * @param {SplitKey} key The key for the new client instance. - * @param {string=} trafficType The traffic type of the provided key. * @returns {IBrowserClient} The client instance. */ - client(key: SplitKey, trafficType?: string): IBrowserClient + client(key: SplitKey): IBrowserClient + /** + * Returns a manager instance of the SDK to explore available information. + * @function manager + * @returns {IManager} The manager instance. + */ + manager(): IManager, /** * User consent API. * @property UserConsent @@ -1441,14 +1264,16 @@ declare namespace SplitIO { manager(): IAsyncManager } /** - * This represents the interface for the Client instance with synchronous storage. + * This represents the interface for the Client instance on server-side, where the user key is not bound to the instance and must be provided on each method call. + * This interface is available in NodeJS, or when importing the 'server' sub-package (e.g., `import { SplitFactory } from '@splitsoftware/splitio/server'`). + * * @interface IClient * @extends IBasicClient */ interface IClient extends IBasicClient { /** * Returns a Treatment value, which is the treatment string for the given feature. - * For usage on NodeJS as we don't have only one key. + * * @function getTreatment * @param {string} key - The string key representing the consumer. * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. @@ -1456,18 +1281,9 @@ declare namespace SplitIO { * @returns {Treatment} The treatment string. */ getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes): Treatment, - /** - * Returns a Treatment value, which is the treatment string for the given feature. - * For usage on the Browser as we defined the key on the settings. - * @function getTreatment - * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatment} The treatment string. - */ - getTreatment(featureFlagName: string, attributes?: Attributes): Treatment, /** * Returns a TreatmentWithConfig value, which is an object with both treatment and config string for the given feature. - * For usage on NodeJS as we don't have only one key. + * * @function getTreatmentWithConfig * @param {string} key - The string key representing the consumer. * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. @@ -1476,20 +1292,9 @@ declare namespace SplitIO { * configuration stringified JSON (or null if there was no config for that treatment). */ getTreatmentWithConfig(key: SplitKey, featureFlagName: string, attributes?: Attributes): TreatmentWithConfig, - /** - * Returns a TreatmentWithConfig value, which an object with both treatment and config string for the given feature. - * For usage on the Browser as we defined the key on the settings. - * @function getTreatmentWithConfig - * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {TreatmentWithConfig} The TreatmentWithConfig, the object containing the treatment string and the - * configuration stringified JSON (or null if there was no config for that treatment). - */ - getTreatmentWithConfig(featureFlagName: string, attributes?: Attributes): TreatmentWithConfig, /** * Returns a Treatments value, which is an object map with the treatments for the given features. - * 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 getTreatments * @param {string} key - The string key representing the consumer. * @param {Array} featureFlagNames - An array of the feature flag names we want to get the treatments. @@ -1497,19 +1302,9 @@ declare namespace SplitIO { * @returns {Treatments} The treatments object map. */ getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): Treatments, - /** - * Returns a Treatments value, which is an object map with the treatments for the given features. - * For usage on the Browser as we defined the key on the settings. - * NOTE: Treatment will be a promise only in async storages, like REDIS. - * @function getTreatments - * @param {Array} featureFlagNames - An array of the feature flags names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The treatments object map. - */ - getTreatments(featureFlagNames: string[], attributes?: Attributes): Treatments, /** * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both 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} featureFlagNames - An array of the feature flag names we want to get the treatments. @@ -1517,17 +1312,9 @@ declare namespace SplitIO { * @returns {TreatmentsWithConfig} The map with all the TreatmentWithConfig objects */ getTreatmentsWithConfig(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the given features. - * For usage on the Browser as we defined the key on the settings. - * @function getTreatmentsWithConfig - * @param {Array} featureFlagNames - An array of the feature flag names we want 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(featureFlagNames: string[], attributes?: Attributes): TreatmentsWithConfig, /** * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. + * * @function getTreatmentsByFlagSet * @param {string} key - The string key representing the consumer. * @param {string} flagSet - The flag set name we want to get the treatments. @@ -1535,16 +1322,9 @@ declare namespace SplitIO { * @returns {Treatments} The map with all the Treatments objects */ getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): Treatments, - /** - * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. - * @function getTreatmentsByFlagSet - * @param {string} flagSet - The flag set name we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The map with all the Treatments objects - */ - getTreatmentsByFlagSet(flagSet: string, attributes?: Attributes): Treatments, /** * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag set. + * * @function getTreatmentsWithConfigByFlagSet * @param {string} key - The string key representing the consumer. * @param {string} flagSet - The flag set name we want to get the treatments. @@ -1552,16 +1332,9 @@ declare namespace SplitIO { * @returns {TreatmentsWithConfig} The map with all the TreatmentWithConfig objects */ getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): TreatmentsWithConfig, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag set. - * @function getTreatmentsWithConfigByFlagSet - * @param {string} flagSet - The flag set name we want 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 - */ - getTreatmentsWithConfigByFlagSet(flagSet: string, attributes?: Attributes): TreatmentsWithConfig, /** * Returns a Returns a Treatments value, which is an object with both treatment and config string for to the feature flags related to the given flag sets. + * * @function getTreatmentsByFlagSets * @param {string} key - The string key representing the consumer. * @param {Array} flagSets - An array of the flag set names we want to get the treatments. @@ -1569,16 +1342,9 @@ declare namespace SplitIO { * @returns {Treatments} The map with all the Treatments objects */ getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): Treatments, - /** - * Returns a Returns a Treatments value, which is an object with both treatment and config string for to the feature flags related to the given flag sets. - * @function getTreatmentsByFlagSets - * @param {Array} flagSets - An array of the flag set names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The map with all the Treatments objects - */ - getTreatmentsByFlagSets(flagSets: string[], attributes?: Attributes): Treatments, /** * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag sets. + * * @function getTreatmentsWithConfigByFlagSets * @param {string} key - The string key representing the consumer. * @param {Array} flagSets - An array of the flag set names we want to get the treatments. @@ -1586,54 +1352,111 @@ declare namespace SplitIO { * @returns {TreatmentsWithConfig} The map with all the TreatmentWithConfig objects */ getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag sets. - * @function getTreatmentsWithConfigByFlagSets - * @param {Array} flagSets - An array of the flag set names we want 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 - */ - getTreatmentsWithConfigByFlagSets(flagSets: string[], attributes?: Attributes): TreatmentsWithConfig, /** * Tracks an event to be fed to the results product on Split user interface. - * For usage on NodeJS as we don't have only one key. + * * @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} trafficType - The traffic type of the entity related to this event. See {@link https://help.split.io/hc/en-us/articles/360019916311-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 successfully or not. */ track(key: SplitIO.SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, + } + /** + * This represents the interface for the Client instance on client-side, where the user key is bound to the instance on creation and does not need to be provided on each method call. + * This interface is the default when importing the SDK in the Browser, or when importing the 'client' sub-package (e.g., `import { SplitFactory } from '@splitsoftware/splitio/client'`). + * + * @interface IBrowserClient + * @extends IBasicClient + */ + interface IBrowserClient extends IBasicClient { /** - * Tracks an event to be fed to the results product on Split user interface. - * For usage on the Browser as we defined the key on the settings. - * @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. + * Returns a Treatment value, which is the treatment string for the given feature. + * + * @function getTreatment + * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. + * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. + * @returns {Treatment} The treatment string. */ - track(trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, + getTreatment(featureFlagName: string, attributes?: Attributes): Treatment, + /** + * Returns a TreatmentWithConfig value, which an object with both treatment and config string for the given feature. + * + * @function getTreatmentWithConfig + * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. + * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. + * @returns {TreatmentWithConfig} The TreatmentWithConfig, the object containing the treatment string and the + * configuration stringified JSON (or null if there was no config for that treatment). + */ + getTreatmentWithConfig(featureFlagName: string, attributes?: Attributes): TreatmentWithConfig, + /** + * Returns a Treatments value, which is an object map with the treatments for the given features. + * + * @function getTreatments + * @param {Array} featureFlagNames - An array of the feature flags names we want to get the treatments. + * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. + * @returns {Treatments} The treatments object map. + */ + getTreatments(featureFlagNames: string[], attributes?: Attributes): Treatments, + /** + * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the given features. + * + * @function getTreatmentsWithConfig + * @param {Array} featureFlagNames - An array of the feature flag names we want 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(featureFlagNames: string[], attributes?: Attributes): TreatmentsWithConfig, + /** + * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. + * + * @function getTreatmentsByFlagSet + * @param {string} flagSet - The flag set name we want to get the treatments. + * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. + * @returns {Treatments} The map with all the Treatments objects + */ + getTreatmentsByFlagSet(flagSet: string, attributes?: Attributes): Treatments, + /** + * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag set. + * + * @function getTreatmentsWithConfigByFlagSet + * @param {string} flagSet - The flag set name we want 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 + */ + getTreatmentsWithConfigByFlagSet(flagSet: string, attributes?: Attributes): TreatmentsWithConfig, + /** + * Returns a Returns a Treatments value, which is an object with both treatment and config string for to the feature flags related to the given flag sets. + * + * @function getTreatmentsByFlagSets + * @param {Array} flagSets - An array of the flag set names we want to get the treatments. + * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. + * @returns {Treatments} The map with all the Treatments objects + */ + getTreatmentsByFlagSets(flagSets: string[], attributes?: Attributes): Treatments, + /** + * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag sets. + * + * @function getTreatmentsWithConfigByFlagSets + * @param {Array} flagSets - An array of the flag set names we want 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 + */ + getTreatmentsWithConfigByFlagSets(flagSets: string[], attributes?: Attributes): TreatmentsWithConfig, /** * Tracks an event to be fed to the results product on Split user interface. - * For usage on the Browser if we defined the key and also the trafficType on the settings. + * * @function track + * @param {string} trafficType - The traffic type of the entity related to this event. See {@link https://help.split.io/hc/en-us/articles/360019916311-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 successfully or not. */ - track(eventType: string, value?: number, properties?: Properties): boolean - } - /** - * This represents the interface for the Client instance with attributes binding. - * @interface IBrowserClient - * @Extends IClient - */ - interface IBrowserClient extends IClient { + track(trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, /** * Add an attribute to client's in memory attributes storage. * @@ -1677,15 +1500,17 @@ declare namespace SplitIO { clearAttributes(): boolean } /** - * This represents the interface for the Client instance with asynchronous storage. + * This represents the interface for the Client instance on server-side with asynchronous storage, like REDIS. + * User key is not bound to the instance and must be provided on each method call, which returns a promise. + * This interface is available in NodeJS, or when importing the 'server' sub-package (e.g., `import { SplitFactory } from '@splitsoftware/splitio/server'`). + * * @interface IAsyncClient * @extends IBasicClient */ 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} featureFlagName - The string that represents the feature flag we want to get the treatment. @@ -1695,8 +1520,7 @@ declare namespace SplitIO { getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes): AsyncTreatment, /** * Returns a TreatmentWithConfig value, which will be (or eventually be) an object 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} featureFlagName - The string that represents the feature flag we want to get the treatment. @@ -1706,7 +1530,7 @@ declare namespace SplitIO { getTreatmentWithConfig(key: SplitKey, featureFlagName: string, attributes?: Attributes): AsyncTreatmentWithConfig, /** * Returns a Treatments value, which will be (or eventually be) an object map 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} featureFlagNames - An array of the feature flag names we want to get the treatments. @@ -1716,7 +1540,7 @@ declare namespace SplitIO { getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): AsyncTreatments, /** * Returns a TreatmentsWithConfig value, which will be (or eventually be) an object map with the TreatmentWithConfig (an object with both 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} featureFlagNames - An array of the feature flag names we want to get the treatments. @@ -1726,7 +1550,7 @@ declare namespace SplitIO { getTreatmentsWithConfig(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): AsyncTreatmentsWithConfig, /** * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. - * For usage on NodeJS as we don't have only one key. + * * @function getTreatmentsByFlagSet * @param {string} key - The string key representing the consumer. * @param {string} flagSet - The flag set name we want to get the treatments. @@ -1736,7 +1560,7 @@ declare namespace SplitIO { getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): AsyncTreatments, /** * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag set. - * For usage on NodeJS as we don't have only one key. + * * @function getTreatmentsWithConfigByFlagSet * @param {string} flagSet - The flag set name we want to get the treatments. * @param {string} key - The string key representing the consumer. @@ -1746,7 +1570,7 @@ declare namespace SplitIO { getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): AsyncTreatmentsWithConfig, /** * Returns a Returns a Treatments value, which is an object with both treatment and config string for to the feature flags related to the given flag sets. - * For usage on NodeJS as we don't have only one key. + * * @function getTreatmentsByFlagSets * @param {string} key - The string key representing the consumer. * @param {Array} flagSets - An array of the flag set names we want to get the treatments. @@ -1756,7 +1580,7 @@ declare namespace SplitIO { getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): AsyncTreatments, /** * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag sets. - * For usage on NodeJS as we don't have only one key. + * * @function getTreatmentsWithConfigByFlagSets * @param {string} key - The string key representing the consumer. * @param {Array} flagSets - An array of the flag set names we want to get the treatments. @@ -1766,9 +1590,10 @@ declare namespace SplitIO { getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): AsyncTreatmentsWithConfig, /** * Tracks an event to be fed to the results product on Split user interface, 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} trafficType - The traffic type of the entity related to this event. See {@link https://help.split.io/hc/en-us/articles/360019916311-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. From aaad4a23c796af3b036ad112e09a5c740fd84eea Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 8 Oct 2024 17:55:11 -0300 Subject: [PATCH 04/20] Remove lib folder --- lib/factory/package.json | 4 ---- lib/platform/getEventSource/package.json | 4 ---- lib/platform/getFetch/package.json | 4 ---- lib/platform/package.json | 4 ---- lib/settings/package.json | 4 ---- 5 files changed, 20 deletions(-) delete mode 100644 lib/factory/package.json delete mode 100644 lib/platform/getEventSource/package.json delete mode 100644 lib/platform/getFetch/package.json delete mode 100644 lib/platform/package.json delete mode 100644 lib/settings/package.json diff --git a/lib/factory/package.json b/lib/factory/package.json deleted file mode 100644 index a19625907..000000000 --- a/lib/factory/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "./node.js", - "browser": "./browser.js" -} diff --git a/lib/platform/getEventSource/package.json b/lib/platform/getEventSource/package.json deleted file mode 100644 index a19625907..000000000 --- a/lib/platform/getEventSource/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "./node.js", - "browser": "./browser.js" -} diff --git a/lib/platform/getFetch/package.json b/lib/platform/getFetch/package.json deleted file mode 100644 index a19625907..000000000 --- a/lib/platform/getFetch/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "./node.js", - "browser": "./browser.js" -} diff --git a/lib/platform/package.json b/lib/platform/package.json deleted file mode 100644 index a19625907..000000000 --- a/lib/platform/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "./node.js", - "browser": "./browser.js" -} diff --git a/lib/settings/package.json b/lib/settings/package.json deleted file mode 100644 index a19625907..000000000 --- a/lib/settings/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "./node.js", - "browser": "./browser.js" -} From 7c0d0506d26249e5be5a9124edb28a01a5070357 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 8 Oct 2024 18:29:29 -0300 Subject: [PATCH 05/20] rc --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d28295fdb..e90c20e76 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/breaking_changes' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/breaking_changes' }} strategy: matrix: environment: From 3c1034b0dd9f7154eb2312b68f9d465773998ff2 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 9 Oct 2024 15:30:56 -0300 Subject: [PATCH 06/20] Update changelog entry --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES.txt | 12 +++++++++--- types/splitio.d.ts | 12 +++++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index e90c20e76..d28295fdb 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/breaking_changes' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/breaking_changes' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} strategy: matrix: environment: diff --git a/CHANGES.txt b/CHANGES.txt index 6ec22cc7b..bb8faf1d9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,9 +2,15 @@ - Added support for targeting rules based on large segments for browsers. - Added `factory.destroy()` method, which invokes the `destroy` method of all clients created by the factory. - Updated @splitsoftware/splitio-commons package to version 2.0.0 that includes major updates and updated some transitive dependencies for vulnerability fixes. + - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. - BREAKING CHANGES: - - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. - - Drop support for NodeJS v6. The SDK now requires NodeJS v14 or above. + - Dropped support for NodeJS v6. The SDK now requires NodeJS v14 or above. + - Removed internal ponyfills for the `Map`, `Set`, and `Array.from` global objects, dropping support for IE and other outdated browsers. The SDK now requires the runtime environment to support these features natively or provide a polyfill. + - Removed the deprecated `GOOGLE_ANALYTICS_TO_SPLIT` and `SPLIT_TO_GOOGLE_ANALYTICS` integrations. The `integrations` configuration option has been removed from the SDK factory configuration, along with the associated interfaces in the TypeScript definitions. + - Removed the `core.trafficType` configuration option in Browser (`SplitIO.IBrowserSettings['core']['trafficType]`) and the `trafficType` parameter from the SDK `client()` method in Browser (`SplitIO.IBrowserSDK['client']`). As a result, traffic types can no longer be bound to SDK clients, and the traffic type must be provided in the `track` method. + - TypeScript definitions: + - Removed an overloaded `client` method in the `SplitIO.ISDK` interface that accepted `key` and `trafficType` parameters. This interface corresponds to the SDK factory instance in NodeJS, which, unlike `SplitIO.IBrowserSDK` for the Browser, does not handle multiple client instances based on keys. + - Updated the `SplitIO.IBrowserSDK` and `SplitIO.IBrowserClient` interfaces to no longer extend the `SplitIO.ISDK` and `SplitIO.IClient` interfaces respectively, as the SDK factory instance in NodeJS or server-side (`SplitIO.ISDK`) has a different API than the SDK client instance in the Browser or client-side (`SplitIO.IBrowserClient`). 10.28.0 (September 6, 2024) - Updated @splitsoftware/splitio-commons package to version 1.17.0 that includes minor updates: @@ -515,7 +521,7 @@ - Bugfixing - Return correct label when consulted Split is not found. 9.1.1 (May 03, 2017) - - Bugfixing - Fixed invalid behaviour when using native Fetch API and comparing statusText + - Bugfixing - Fixed invalid behavior when using native Fetch API and comparing statusText instead of resp.ok 9.1.0 (April 21, 2017) diff --git a/types/splitio.d.ts b/types/splitio.d.ts index 7abd18d7c..596fd9a80 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -441,7 +441,17 @@ interface IStatusInterface extends EventEmitter { /** * Returns a promise that resolves 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, the `ready` method will return a resolved promise once the SDK is ready. - * You must handle the promise rejection to avoid an unhandled promise rejection error, or you can set the `startup.readyTimeout` configuration option to 0 to avoid the timeout and thus the rejection. + * + * 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} From e0dd572680ebf1563ae44c08819d49b0933ecf2b Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 9 Oct 2024 18:27:43 -0300 Subject: [PATCH 07/20] Update changelog entry --- CHANGES.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index bb8faf1d9..4d6b2a445 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,9 +5,9 @@ - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. - BREAKING CHANGES: - Dropped support for NodeJS v6. The SDK now requires NodeJS v14 or above. - - Removed internal ponyfills for the `Map`, `Set`, and `Array.from` global objects, dropping support for IE and other outdated browsers. The SDK now requires the runtime environment to support these features natively or provide a polyfill. + - Removed internal ponyfills for the `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 provide a polyfill. - Removed the deprecated `GOOGLE_ANALYTICS_TO_SPLIT` and `SPLIT_TO_GOOGLE_ANALYTICS` integrations. The `integrations` configuration option has been removed from the SDK factory configuration, along with the associated interfaces in the TypeScript definitions. - - Removed the `core.trafficType` configuration option in Browser (`SplitIO.IBrowserSettings['core']['trafficType]`) and the `trafficType` parameter from the SDK `client()` method in Browser (`SplitIO.IBrowserSDK['client']`). As a result, traffic types can no longer be bound to SDK clients, and the traffic type must be provided in the `track` method. + - Removed the `core.trafficType` configuration option (`SplitIO.IBrowserSettings['core']['trafficType]`) and the `trafficType` parameter from the SDK `client()` method in Browser (`SplitIO.IBrowserSDK['client']`). As a result, traffic types can no longer be bound to SDK clients, and the traffic type must be provided in the `track` method. - TypeScript definitions: - Removed an overloaded `client` method in the `SplitIO.ISDK` interface that accepted `key` and `trafficType` parameters. This interface corresponds to the SDK factory instance in NodeJS, which, unlike `SplitIO.IBrowserSDK` for the Browser, does not handle multiple client instances based on keys. - Updated the `SplitIO.IBrowserSDK` and `SplitIO.IBrowserClient` interfaces to no longer extend the `SplitIO.ISDK` and `SplitIO.IClient` interfaces respectively, as the SDK factory instance in NodeJS or server-side (`SplitIO.ISDK`) has a different API than the SDK client instance in the Browser or client-side (`SplitIO.IBrowserClient`). From 79e33e70d2a9ee36940a7ddac591281abd654e3a Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 18 Oct 2024 17:31:55 -0300 Subject: [PATCH 08/20] Update JS-commons dep --- package-lock.json | 14 +++++++------- package.json | 2 +- types/splitio.d.ts | 6 ------ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9342fd31..40bd9f43a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "11.0.0-rc.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.0", + "@splitsoftware/splitio-commons": "2.0.0-rc.1", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", @@ -870,9 +870,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.0.tgz", - "integrity": "sha512-iNuGugPMXQ/+k+uSDyhsvwkaGdzQrRaxRtP1sv58STKQFwww1smPxRA1gKfawoQm04quEHtLMKYm25t6VL0fJw==", + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.1.tgz", + "integrity": "sha512-tjIDgNnrwOKphYtWKNv0HOU7LJQ+0ljgbmknhi3H7MDptvnwG7o8DHKtoAtuljcEqVjosLmhgzOxzTY9MGZruw==", "dependencies": { "tslib": "^2.3.1" }, @@ -8587,9 +8587,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.0.tgz", - "integrity": "sha512-iNuGugPMXQ/+k+uSDyhsvwkaGdzQrRaxRtP1sv58STKQFwww1smPxRA1gKfawoQm04quEHtLMKYm25t6VL0fJw==", + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.1.tgz", + "integrity": "sha512-tjIDgNnrwOKphYtWKNv0HOU7LJQ+0ljgbmknhi3H7MDptvnwG7o8DHKtoAtuljcEqVjosLmhgzOxzTY9MGZruw==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index 12856a9ac..7eaf5130f 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.0", + "@splitsoftware/splitio-commons": "2.0.0-rc.1", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", diff --git a/types/splitio.d.ts b/types/splitio.d.ts index a8bbed6aa..596fd9a80 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -1248,12 +1248,6 @@ declare namespace SplitIO { * @returns {IManager} The manager instance. */ manager(): IManager, - /** - * Returns a manager instance of the SDK to explore available information. - * @function manager - * @returns {IManager} The manager instance. - */ - manager(): IManager, /** * User consent API. * @property UserConsent From 7a9782cb3548c80a4b01a289d3db034935dc88fb Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 18 Oct 2024 17:33:03 -0300 Subject: [PATCH 09/20] rc --- package-lock.json | 4 ++-- package.json | 2 +- src/settings/defaults/version.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40bd9f43a..f0c4ffe5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.0", + "version": "11.0.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.0", + "version": "11.0.0-rc.1", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.0.0-rc.1", diff --git a/package.json b/package.json index 7eaf5130f..8a0c2cd88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.0", + "version": "11.0.0-rc.1", "description": "Split SDK", "files": [ "README.md", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 7f7b63b6a..b631429a8 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.0.0-rc.0'; +export const packageVersion = '11.0.0-rc.1'; From a3230a2a64082a27a760c4247c67c3133a170ad2 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 18 Oct 2024 17:44:14 -0300 Subject: [PATCH 10/20] Fix test --- ts-tests/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 1a7585845..2440be58a 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -201,7 +201,6 @@ asyncManager = AsyncSDK.manager(); // Browser client for attributes binding browserClient = BrowserSDK.client(); browserClient = BrowserSDK.client('a customer key'); -browserClient = BrowserSDK.client('a customer key', 'a traffic type'); // Logger SDK.Logger.enable(); From c07824951ba39c669102a2f4dd6e0c05c06d9ad4 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 25 Oct 2024 02:34:17 -0300 Subject: [PATCH 11/20] Internal refactor after removing sync.localhostMode option in JS-commons --- package-lock.json | 14 +++++++------- package.json | 2 +- src/factory/browser.js | 3 ++- src/factory/node.js | 3 ++- src/settings/browser.js | 2 -- src/settings/node.js | 2 -- src/sync/offline/LocalhostFromFile.js | 9 ++------- 7 files changed, 14 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0c4ffe5e..64c5a0e6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "11.0.0-rc.1", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.1", + "@splitsoftware/splitio-commons": "2.0.0-rc.3", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", @@ -870,9 +870,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.1.tgz", - "integrity": "sha512-tjIDgNnrwOKphYtWKNv0HOU7LJQ+0ljgbmknhi3H7MDptvnwG7o8DHKtoAtuljcEqVjosLmhgzOxzTY9MGZruw==", + "version": "2.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.3.tgz", + "integrity": "sha512-XkDbULWBg6nw061b4Vc425JyrpDe5nSypoScO4eVsFbgcCqUPlGbr+s9bfriwNFyZe2Q29ijIlyGM06TCt27kQ==", "dependencies": { "tslib": "^2.3.1" }, @@ -8587,9 +8587,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.1.tgz", - "integrity": "sha512-tjIDgNnrwOKphYtWKNv0HOU7LJQ+0ljgbmknhi3H7MDptvnwG7o8DHKtoAtuljcEqVjosLmhgzOxzTY9MGZruw==", + "version": "2.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.3.tgz", + "integrity": "sha512-XkDbULWBg6nw061b4Vc425JyrpDe5nSypoScO4eVsFbgcCqUPlGbr+s9bfriwNFyZe2Q29ijIlyGM06TCt27kQ==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index 8a0c2cd88..55f3ad188 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.1", + "@splitsoftware/splitio-commons": "2.0.0-rc.3", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", diff --git a/src/factory/browser.js b/src/factory/browser.js index b06eac524..8b71ed235 100644 --- a/src/factory/browser.js +++ b/src/factory/browser.js @@ -11,6 +11,7 @@ import { __InLocalStorageMockFactory } from '@splitsoftware/splitio-commons/src/ import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory'; import { LOCALHOST_MODE, STORAGE_LOCALSTORAGE } from '@splitsoftware/splitio-commons/src/utils/constants'; import { createUserConsentAPI } from '@splitsoftware/splitio-commons/src/consent/sdkUserConsent'; +import { localhostFromObjectFactory } from '@splitsoftware/splitio-commons/src/sync/offline/LocalhostFromObject'; import { settingsFactory } from '../settings/browser'; import { platform, SignalListener } from '../platform'; @@ -60,7 +61,7 @@ function getModules(settings) { switch (settings.mode) { case LOCALHOST_MODE: modules.splitApiFactory = undefined; - modules.syncManagerFactory = settings.sync.localhostMode; + modules.syncManagerFactory = localhostFromObjectFactory; modules.SignalListener = undefined; break; } diff --git a/src/factory/node.js b/src/factory/node.js index d8141037a..4142741b9 100644 --- a/src/factory/node.js +++ b/src/factory/node.js @@ -10,6 +10,7 @@ import { impressionObserverSSFactory } from '@splitsoftware/splitio-commons/src/ import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory'; import { CONSUMER_MODE, LOCALHOST_MODE } from '@splitsoftware/splitio-commons/src/utils/constants'; +import { localhostFromFileFactory } from '../sync/offline/LocalhostFromFile'; import { settingsFactory } from '../settings/node'; import { platform, SignalListener } from '../platform'; import { bloomFilterFactory } from '../platform/filter/bloomFilter'; @@ -53,7 +54,7 @@ function getModules(settings) { switch (settings.mode) { case LOCALHOST_MODE: modules.splitApiFactory = undefined; - modules.syncManagerFactory = settings.sync.localhostMode; + modules.syncManagerFactory = localhostFromFileFactory; modules.SignalListener = undefined; break; case CONSUMER_MODE: diff --git a/src/settings/browser.js b/src/settings/browser.js index 5a1ae432b..584b11a23 100644 --- a/src/settings/browser.js +++ b/src/settings/browser.js @@ -1,7 +1,6 @@ import { settingsValidation } from '@splitsoftware/splitio-commons/src/utils/settingsValidation'; import { validateRuntime } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/runtime'; import { validateLogger } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/logger/builtinLogger'; -import { LocalhostFromObject } from '@splitsoftware/splitio-commons/src/sync/offline/LocalhostFromObject'; import { validateConsent } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/consent'; import { defaults } from './defaults/browser'; @@ -13,7 +12,6 @@ const params = { runtime: validateRuntime, storage: validateStorage, logger: validateLogger, - localhost: () => LocalhostFromObject(), consent: validateConsent, }; diff --git a/src/settings/node.js b/src/settings/node.js index f7664b3f6..5fe7d5535 100644 --- a/src/settings/node.js +++ b/src/settings/node.js @@ -1,6 +1,5 @@ import { settingsValidation } from '@splitsoftware/splitio-commons/src/utils/settingsValidation'; import { validateLogger } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/logger/builtinLogger'; -import { LocalhostFromFile } from '../sync/offline/LocalhostFromFile'; import { defaults } from './defaults/node'; import { validateStorage } from './storage/node'; @@ -13,7 +12,6 @@ const params = { runtime: validateRuntime, storage: validateStorage, logger: validateLogger, - localhost: () => LocalhostFromFile(), flagSpec: () => FLAG_SPEC_VERSION // In Node.js the SDK ignores `config.integrations`, so a validator for integrations is not required }; diff --git a/src/sync/offline/LocalhostFromFile.js b/src/sync/offline/LocalhostFromFile.js index 3f63173ac..3dca10929 100644 --- a/src/sync/offline/LocalhostFromFile.js +++ b/src/sync/offline/LocalhostFromFile.js @@ -1,11 +1,6 @@ import { splitsParserFromFileFactory } from './splitsParserFromFile'; import { syncManagerOfflineFactory } from '@splitsoftware/splitio-commons/src/sync/offline/syncManagerOffline'; -// Singleton instance of the factory function for offline SyncManager from YAML file (a.k.a. localhostFromFile) +// Singleton instance of the factory function for offline SyncManager from YAML file // It uses NodeJS APIs. -const localhostFromFile = syncManagerOfflineFactory(splitsParserFromFileFactory); -localhostFromFile.type = 'LocalhostFromFile'; - -export function LocalhostFromFile() { - return localhostFromFile; -} +export const localhostFromFileFactory = syncManagerOfflineFactory(splitsParserFromFileFactory); From d7d6eb6cc167c3e6c20ea0aa2faf03cd57936368 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 25 Oct 2024 18:09:48 -0300 Subject: [PATCH 12/20] Move SplitIO namespace definition from JS SDK to JS-Commons and merge --- package-lock.json | 21 +- package.json | 9 +- scripts/ts-tests.sh | 28 - src/settings/defaults/version.js | 2 +- ts-tests/index.ts | 199 ++-- ts-tests/package.json | 12 - ts-tests/tsconfig.json | 3 +- types/client/index.d.ts | 5 +- types/index.d.ts | 8 +- types/server/index.d.ts | 7 +- types/splitio.d.ts | 1666 ------------------------------ 11 files changed, 125 insertions(+), 1835 deletions(-) delete mode 100755 scripts/ts-tests.sh delete mode 100644 ts-tests/package.json delete mode 100644 types/splitio.d.ts diff --git a/package-lock.json b/package-lock.json index 64c5a0e6a..5024d5fc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.1", + "version": "11.0.0-rc.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.1", + "version": "11.0.0-rc.3", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.3", - "@types/ioredis": "^4.28.0", + "@splitsoftware/splitio-commons": "2.0.0-rc.4", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -870,10 +869,11 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.3", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.3.tgz", - "integrity": "sha512-XkDbULWBg6nw061b4Vc425JyrpDe5nSypoScO4eVsFbgcCqUPlGbr+s9bfriwNFyZe2Q29ijIlyGM06TCt27kQ==", + "version": "2.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.4.tgz", + "integrity": "sha512-z0rm4X9oh7LdIcHeEkh6Ca3JzfdhJ0IH3r7nZ6ghL0AXmPzbezoDswxjKOe/WYBbTW3utsgLqTTjr9Ww/b/hUw==", "dependencies": { + "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" }, "peerDependencies": { @@ -8587,10 +8587,11 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.3", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.3.tgz", - "integrity": "sha512-XkDbULWBg6nw061b4Vc425JyrpDe5nSypoScO4eVsFbgcCqUPlGbr+s9bfriwNFyZe2Q29ijIlyGM06TCt27kQ==", + "version": "2.0.0-rc.4", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.4.tgz", + "integrity": "sha512-z0rm4X9oh7LdIcHeEkh6Ca3JzfdhJ0IH3r7nZ6ghL0AXmPzbezoDswxjKOe/WYBbTW3utsgLqTTjr9Ww/b/hUw==", "requires": { + "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" } }, diff --git a/package.json b/package.json index 55f3ad188..6d564c8b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.1", + "version": "11.0.0-rc.3", "description": "Split SDK", "files": [ "README.md", @@ -38,8 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.3", - "@types/ioredis": "^4.28.0", + "@splitsoftware/splitio-commons": "2.0.0-rc.4", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -109,9 +108,7 @@ "test-node-e2e-errorCatching": "cross-env NODE_ENV=test tape -r ./ts-node.register src/__tests__/errorCatching/node.spec.js | tap-min", "test-node-e2e-push": "cross-env NODE_ENV=test tape -r ./ts-node.register src/__tests__/push/node.spec.js | tap-min", "test-node-e2e-redis": "cross-env NODE_ENV=test tape -r ./ts-node.register src/__tests__/consumer/node_redis.spec.js | tap-min", - "pretest-ts-decls": "npm run build-esm && npm run build-cjs && npm link", - "test-ts-decls": "./scripts/ts-tests.sh", - "posttest-ts-decls": "npm rm --location=global @splitsoftware/splitio && npm install", + "test-ts-decls": "tsc --build ts-tests", "test": "npm run test-node && npm run test-browser", "all": "npm run check && npm run build && npm run test-ts-decls && npm run test", "publish:rc": "npm run check && npm run build && npm publish --tag canary", diff --git a/scripts/ts-tests.sh b/scripts/ts-tests.sh deleted file mode 100755 index 2263e923d..000000000 --- a/scripts/ts-tests.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -cd ts-tests ## Go to typescript tests folder -echo "Installing dependencies for TypeScript declarations testing..." -npm install ## Install dependencies -npm install @types/node@6.0.31 ## Install type definitions for Node.js v6.x (the oldest supported version) -echo "Dependencies installed, linking the package." -npm link @splitsoftware/splitio ## Link to the cloned code -echo "Running tsc compiler." -./node_modules/.bin/tsc ## Run typescript compiler. No need for flags as we have a tsconfig.json file - -echo "Testing again with the latest @types/node version..." -npm install @types/node@14 ## Install latest type definitions for Node.js -echo "Dependencies installed, linking the package." -npm link @splitsoftware/splitio ## Link to the cloned code -echo "Running tsc compiler." -./node_modules/.bin/tsc ## Run typescript compiler. No need for flags as we have a tsconfig.json file - -if [ $? -eq 0 ] -then - echo "✅ Successfully compiled TS tests." - npm unlink @splitsoftware/splitio - exit 0 -else - echo "☠️ Error compiling TS tests." - npm unlink @splitsoftware/splitio - exit 1 -fi diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index b631429a8..818b1f165 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.0.0-rc.1'; +export const packageVersion = '11.0.0-rc.3'; diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 2440be58a..1cbe834ea 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -11,7 +11,7 @@ * @author Nico Zelaya */ -import { SplitFactory } from '@splitsoftware/splitio'; +import { SplitFactory } from '../types/index'; let stringPromise: Promise; let splitNamesPromise: Promise; @@ -25,19 +25,19 @@ let trackPromise: Promise; /**** Interfaces ****/ // Facade return interface -let SDK: SplitIO.ISDK; -let AsyncSDK: SplitIO.IAsyncSDK; -let BrowserSDK: SplitIO.IBrowserSDK; +let NodeSDK: SplitIO.INodeSDK; +let AsyncSDK: SplitIO.INodeAsyncSDK; +let BrowserSDK: SplitIO.ISDK; // Settings interfaces let nodeSettings: SplitIO.INodeSettings; let asyncSettings: SplitIO.INodeAsyncSettings; let browserSettings: SplitIO.IBrowserSettings; // Client & Manager APIs -let client: SplitIO.IClient; +let nodeClient: SplitIO.INodeClient; let manager: SplitIO.IManager; -let asyncClient: SplitIO.IAsyncClient; +let nodeAsyncClient: SplitIO.INodeAsyncClient; let asyncManager: SplitIO.IAsyncManager; -let browserClient: SplitIO.IBrowserClient; +let browserClient: SplitIO.IClient; // Utility interfaces let impressionListener: SplitIO.IImpressionListener; @@ -137,7 +137,7 @@ splitViewsAsync = splitViewsPromise; splitKey = 'someKey'; splitKey = splitKeyObj; -/**** Tests for ISDK interface ****/ +/**** Tests for INodeSDK interface ****/ // For node with sync storage nodeSettings = { @@ -162,8 +162,8 @@ browserSettings = { key: 'customer-key' } }; -// With sync settings should return ISDK, if settings have async storage it should return IAsyncSDK -SDK = SplitFactory(nodeSettings); +// With sync settings should return INodeSDK, if settings have async storage it should return INodeAsyncSDK +NodeSDK = SplitFactory(nodeSettings); AsyncSDK = SplitFactory(asyncSettings); BrowserSDK = SplitFactory(browserSettings); @@ -173,43 +173,38 @@ const instantiatedSettingsCore: { key: SplitIO.SplitKey, labelsEnabled: boolean, IPAddressesEnabled: boolean -} = SDK.settings.core; -const instantiatedSettingsMode: ('standalone' | 'consumer') = SDK.settings.mode; -const instantiatedSettingsScheduler: { [key: string]: number } = SDK.settings.scheduler; -const instantiatedSettingsStartup: { [key: string]: number } = SDK.settings.startup; -const instantiatedSettingsStorage: { - prefix: string, - options: Object, - // It can have any of the storages. - type: SplitIO.NodeSyncStorage | SplitIO.NodeAsyncStorage | SplitIO.BrowserStorage -} = SDK.settings.storage; -const instantiatedSettingsUrls: { [key: string]: string } = SDK.settings.urls; -const instantiatedSettingsVersion: string = SDK.settings.version; -let instantiatedSettingsFeatures = SDK.settings.features as SplitIO.MockedFeaturesMap; +} = NodeSDK.settings.core; +const instantiatedSettingsMode: ('standalone' | 'consumer' | 'consumer_partial' | 'localhost') = NodeSDK.settings.mode; +const instantiatedSettingsScheduler: { [key: string]: number } = NodeSDK.settings.scheduler; +const instantiatedSettingsStartup: { [key: string]: number } = NodeSDK.settings.startup; +const instantiatedSettingsStorage = NodeSDK.settings.storage as SplitIO.StorageOptions; +const instantiatedSettingsUrls: { [key: string]: string } = NodeSDK.settings.urls; +const instantiatedSettingsVersion: string = NodeSDK.settings.version; +let instantiatedSettingsFeatures = NodeSDK.settings.features as SplitIO.MockedFeaturesMap; // We should be able to write on features prop. The rest are readonly props. instantiatedSettingsFeatures.something = 'something'; -SDK.settings.features = 'new_file_path'; // Node -SDK.settings.features = { 'split_x': 'on' }; // Browser +NodeSDK.settings.features = 'new_file_path'; // Node +NodeSDK.settings.features = { 'split_x': 'on' }; // Browser // Client and Manager -client = SDK.client(); -manager = SDK.manager(); +nodeClient = NodeSDK.client(); +manager = NodeSDK.manager(); manager = BrowserSDK.manager(); // Today async clients are only possible on Node. Shared client creation not available here. -asyncClient = AsyncSDK.client(); +nodeAsyncClient = AsyncSDK.client(); asyncManager = AsyncSDK.manager(); // Browser client for attributes binding browserClient = BrowserSDK.client(); browserClient = BrowserSDK.client('a customer key'); // Logger -SDK.Logger.enable(); -SDK.Logger.setLogLevel(SDK.Logger.LogLevel.DEBUG); -SDK.Logger.setLogLevel(SDK.Logger.LogLevel.INFO); -SDK.Logger.setLogLevel(SDK.Logger.LogLevel.WARN); -SDK.Logger.setLogLevel(SDK.Logger.LogLevel.ERROR); -SDK.Logger.setLogLevel(SDK.Logger.LogLevel.NONE); -SDK.Logger.disable(); +NodeSDK.Logger.enable(); +NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.DEBUG); +NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.INFO); +NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.WARN); +NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.ERROR); +NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.NONE); +NodeSDK.Logger.disable(); AsyncSDK.Logger.enable(); AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.DEBUG); @@ -222,163 +217,163 @@ AsyncSDK.Logger.disable(); /**** Tests for IClient interface ****/ // Events constants we get -const eventConsts: { [key: string]: SplitIO.Event } = client.Event; -splitEvent = client.Event.SDK_READY; -splitEvent = client.Event.SDK_READY_FROM_CACHE; -splitEvent = client.Event.SDK_READY_TIMED_OUT; -splitEvent = client.Event.SDK_UPDATE; +const eventConsts: { [key: string]: SplitIO.Event } = nodeClient.Event; +splitEvent = nodeClient.Event.SDK_READY; +splitEvent = nodeClient.Event.SDK_READY_FROM_CACHE; +splitEvent = nodeClient.Event.SDK_READY_TIMED_OUT; +splitEvent = nodeClient.Event.SDK_UPDATE; // Client implements methods from NodeJS.Events. Testing a few. -client = client.on(splitEvent, () => { }); -const a: boolean = client.emit(splitEvent); -client = client.removeAllListeners(splitEvent); -client = client.removeAllListeners(); -const b: number = client.listenerCount(splitEvent); -let nodeEventEmitter: NodeJS.EventEmitter = client; +nodeClient = nodeClient.on(splitEvent, () => { }); +const a: boolean = nodeClient.emit(splitEvent); +nodeClient = nodeClient.removeAllListeners(splitEvent); +nodeClient = nodeClient.removeAllListeners(); +const b: number = nodeClient.listenerCount(splitEvent); +let nodeEventEmitter: NodeJS.EventEmitter = nodeClient; // Ready, destroy and flush -let promise: Promise = client.ready(); -promise = client.destroy(); -promise = SDK.destroy(); +let promise: Promise = nodeClient.ready(); +promise = nodeClient.destroy(); +promise = NodeSDK.destroy(); // @TODO not public yet -// promise = client.flush(); +// promise = nodeClient.flush(); // We can call getTreatment with or without a key. -treatment = client.getTreatment(splitKey, 'mySplit'); +treatment = nodeClient.getTreatment(splitKey, 'mySplit'); treatment = browserClient.getTreatment('mySplit'); // Attributes parameter is optional on both signatures. -treatment = client.getTreatment(splitKey, 'mySplit', attributes); +treatment = nodeClient.getTreatment(splitKey, 'mySplit', attributes); treatment = browserClient.getTreatment('mySplit', attributes); // We can call getTreatments with or without a key. -treatments = client.getTreatments(splitKey, ['mySplit']); +treatments = nodeClient.getTreatments(splitKey, ['mySplit']); treatments = browserClient.getTreatments(['mySplit']); // Attributes parameter is optional on both signatures. -treatments = client.getTreatments(splitKey, ['mySplit'], attributes); +treatments = nodeClient.getTreatments(splitKey, ['mySplit'], attributes); treatments = browserClient.getTreatments(['mySplit'], attributes); // We can call getTreatmentWithConfig with or without a key. -treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit'); +treatmentWithConfig = nodeClient.getTreatmentWithConfig(splitKey, 'mySplit'); treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit'); // Attributes parameter is optional on both signatures. -treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit', attributes); +treatmentWithConfig = nodeClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit', attributes); // We can call getTreatmentsWithConfig with or without a key. -treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit']); +treatmentsWithConfig = nodeClient.getTreatmentsWithConfig(splitKey, ['mySplit']); treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit']); // Attributes parameter is optional on both signatures. -treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); +treatmentsWithConfig = nodeClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit'], attributes); // We can call getTreatmentsByFlagSet with or without a key. -treatments = client.getTreatmentsByFlagSet(splitKey, 'set_a'); +treatments = nodeClient.getTreatmentsByFlagSet(splitKey, 'set_a'); treatments = browserClient.getTreatmentsByFlagSet('set_a'); // Attributes parameter is optional. -treatments = client.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); +treatments = nodeClient.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); treatments = browserClient.getTreatmentsByFlagSet('set_a', attributes); // We can call getTreatmentsByFlagSets with or without a key. -treatments = client.getTreatmentsByFlagSets(splitKey, ['set_a']); +treatments = nodeClient.getTreatmentsByFlagSets(splitKey, ['set_a']); treatments = browserClient.getTreatmentsByFlagSets(['set_a']); // Attributes parameter is optional. -treatments = client.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); +treatments = nodeClient.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); treatments = browserClient.getTreatmentsByFlagSets(['set_a'], attributes); // We can call getTreatmentsWithConfigByFlagSet with or without a key. -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); +treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSet('set_a'); // Attributes parameter is optional. -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); +treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSet('set_a', attributes); // We can call getTreatmentsWithConfigByFlagSets with or without a key. -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); +treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSets(['set_a']); // Attributes parameter is optional. -treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); +treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSets(['set_a'], attributes); // We can call track with or without a key. -tracked = client.track(splitKey, 'myTrafficType', 'myEventType'); // all params +tracked = nodeClient.track(splitKey, 'myTrafficType', 'myEventType'); // all params tracked = browserClient.track('myTrafficType', 'myEventType'); // key bound, tt provided. // Value parameter is optional on all signatures. -tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10); +tracked = nodeClient.track(splitKey, 'myTrafficType', 'myEventType', 10); tracked = browserClient.track('myTrafficType', 'myEventType', 10); // Properties parameter is optional on all signatures. -tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); +tracked = nodeClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); tracked = browserClient.track('myTrafficType', 'myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); /*** Repeating tests for Async Client ***/ // Events constants we get (same as for sync client, just for interface checking) -const eventConstsAsync: { [key: string]: SplitIO.Event } = asyncClient.Event; -splitEvent = asyncClient.Event.SDK_READY; -splitEvent = asyncClient.Event.SDK_READY_FROM_CACHE; -splitEvent = asyncClient.Event.SDK_READY_TIMED_OUT; -splitEvent = asyncClient.Event.SDK_UPDATE; +const eventConstsAsync: { [key: string]: SplitIO.Event } = nodeAsyncClient.Event; +splitEvent = nodeAsyncClient.Event.SDK_READY; +splitEvent = nodeAsyncClient.Event.SDK_READY_FROM_CACHE; +splitEvent = nodeAsyncClient.Event.SDK_READY_TIMED_OUT; +splitEvent = nodeAsyncClient.Event.SDK_UPDATE; // Client implements methods from NodeJS.Events. (same as for sync client, just for interface checking) -asyncClient = asyncClient.on(splitEvent, () => { }); -const a1: boolean = asyncClient.emit(splitEvent); -asyncClient = asyncClient.removeAllListeners(splitEvent); -asyncClient = asyncClient.removeAllListeners(); -const b1: number = asyncClient.listenerCount(splitEvent); -nodeEventEmitter = asyncClient; +nodeAsyncClient = nodeAsyncClient.on(splitEvent, () => { }); +const a1: boolean = nodeAsyncClient.emit(splitEvent); +nodeAsyncClient = nodeAsyncClient.removeAllListeners(splitEvent); +nodeAsyncClient = nodeAsyncClient.removeAllListeners(); +const b1: number = nodeAsyncClient.listenerCount(splitEvent); +nodeEventEmitter = nodeAsyncClient; // Ready, destroy and flush (same as for sync client, just for interface checking) -promise = asyncClient.ready(); -promise = asyncClient.destroy(); +promise = nodeAsyncClient.ready(); +promise = nodeAsyncClient.destroy(); promise = AsyncSDK.destroy(); // @TODO not public yet -// promise = asyncClient.flush(); +// promise = nodeAsyncClient.flush(); // We can call getTreatment but always with a key. -asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit'); +asyncTreatment = nodeAsyncClient.getTreatment(splitKey, 'mySplit'); // Attributes parameter is optional -asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit', attributes); +asyncTreatment = nodeAsyncClient.getTreatment(splitKey, 'mySplit', attributes); // We can call getTreatments but always with a key. -asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit']); +asyncTreatments = nodeAsyncClient.getTreatments(splitKey, ['mySplit']); // Attributes parameter is optional -asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit'], attributes); +asyncTreatments = nodeAsyncClient.getTreatments(splitKey, ['mySplit'], attributes); // We can call getTreatmentWithConfig but always with a key. -asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit'); +asyncTreatmentWithConfig = nodeAsyncClient.getTreatmentWithConfig(splitKey, 'mySplit'); // Attributes parameter is optional -asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); +asyncTreatmentWithConfig = nodeAsyncClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); // We can call getTreatments but always with a key. -asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit']); +asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfig(splitKey, ['mySplit']); // Attributes parameter is optional -asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); +asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); // We can call getTreatmentsByFlagSet -asyncTreatments = asyncClient.getTreatmentsByFlagSet(splitKey, 'set_a'); +asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSet(splitKey, 'set_a'); // Attributes parameter is optional -asyncTreatments = asyncClient.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); +asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); // We can call getTreatmentsByFlagSets -asyncTreatments = asyncClient.getTreatmentsByFlagSets(splitKey, ['set_a']); +asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSets(splitKey, ['set_a']); // Attributes parameter is optional -asyncTreatments = asyncClient.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); +asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); // We can call getTreatmentsWithConfigByFlagSet -asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); +asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); // Attributes parameter is optional -asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); +asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); // We can call getTreatmentsByFlagSets but always with a key. -asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); +asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); // Attributes parameter is optional -asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); +asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); // We can call track only with a key. -trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType'); // all required params +trackPromise = nodeAsyncClient.track(splitKey, 'myTrafficType', 'myEventType'); // all required params // Value parameter is optional. -trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10); +trackPromise = nodeAsyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10); // Properties parameter is optional -trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); +trackPromise = nodeAsyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); /**** Tests for IManager interface ****/ diff --git a/ts-tests/package.json b/ts-tests/package.json deleted file mode 100644 index d359b9e25..000000000 --- a/ts-tests/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "ts-tests", - "version": "1.0.0", - "description": "SDK tests for TypeScript declaration files", - "author": "Nico Zelaya", - "license": "Apache-2.0", - "repository": "splitio/javascript-client", - "dependencies": { - "@types/node": "^14.18.63", - "typescript": "^3.7.4" - } -} diff --git a/ts-tests/tsconfig.json b/ts-tests/tsconfig.json index 4adc23925..2c1ab20a8 100644 --- a/ts-tests/tsconfig.json +++ b/ts-tests/tsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "noImplicitAny": true, "target": "es5", - "module": "commonjs" + "module": "commonjs", + "noEmit": true, }, "files": [ "index" diff --git a/types/client/index.d.ts b/types/client/index.d.ts index ba6d4a9d4..45efaa984 100644 --- a/types/client/index.d.ts +++ b/types/client/index.d.ts @@ -1,7 +1,8 @@ // Declaration file for JavaScript Split Software SDK // Project: http://www.split.io/ -/// +import '@splitsoftware/splitio-commons'; + export = JsSdk; declare module JsSdk { @@ -10,5 +11,5 @@ declare module JsSdk { * The settings parameter should be an object that complies with the SplitIO.IBrowserSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.IBrowserSDK; + export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.ISDK; } diff --git a/types/index.d.ts b/types/index.d.ts index adaf540dd..2bcd7c7db 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -2,7 +2,7 @@ // Project: http://www.split.io/ // Definitions by: Nico Zelaya -/// +import '@splitsoftware/splitio-commons'; export = JsSdk; @@ -12,17 +12,17 @@ declare module JsSdk { * The settings parameter should be an object that complies with the SplitIO.INodeAsyncSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.IAsyncSDK; + export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.INodeAsyncSDK; /** * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.ISDK; + export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.INodeSDK; /** * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.IBrowserSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.IBrowserSDK; + export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.ISDK; } diff --git a/types/server/index.d.ts b/types/server/index.d.ts index f39f44bf6..f0e305fce 100644 --- a/types/server/index.d.ts +++ b/types/server/index.d.ts @@ -1,7 +1,8 @@ // Declaration file for JavaScript Split Software SDK // Project: http://www.split.io/ -/// +import '@splitsoftware/splitio-commons'; + export = JsSdk; declare module JsSdk { @@ -10,11 +11,11 @@ declare module JsSdk { * The settings parameter should be an object that complies with the SplitIO.INodeAsyncSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.IAsyncSDK; + export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.INodeAsyncSDK; /** * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.ISDK; + export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.INodeSDK; } diff --git a/types/splitio.d.ts b/types/splitio.d.ts deleted file mode 100644 index 596fd9a80..000000000 --- a/types/splitio.d.ts +++ /dev/null @@ -1,1666 +0,0 @@ -// Type definitions for JavaScript and NodeJS Split Software SDK -// Project: http://www.split.io/ -// Definitions by: Nico Zelaya - -import { RedisOptions } from "ioredis"; -import { RequestOptions } from "http"; - -export as namespace SplitIO; -export = SplitIO; - -/** - * NodeJS.EventEmitter interface - * @see {@link https://nodejs.org/api/events.html} - */ -interface EventEmitter { - addListener(event: string | symbol, listener: (...args: any[]) => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; - removeListener(event: string | symbol, listener: (...args: any[]) => void): this; - off(event: string | symbol, listener: (...args: any[]) => void): this; - removeAllListeners(event?: string | symbol): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string | symbol): Function[]; - rawListeners(event: string | symbol): Function[]; - emit(event: string | symbol, ...args: any[]): boolean; - listenerCount(type: string | symbol): number; - // Added in Node 6... - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; - eventNames(): Array; -} -/** - * @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' | 'consumer'; -/** - * Storage types. - * @typedef {string} StorageType - */ -type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS'; -/** - * 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, - 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 - }, - readonly urls: { - events: string, - sdk: string, - auth: string, - streaming: string, - telemetry: string - }, - readonly debug: boolean | LogLevel, - readonly version: string, - /** - * Mocked features map if using in browser, or mocked features file path string if using in NodeJS. - */ - features: SplitIO.MockedFeaturesMap | SplitIO.MockedFeaturesFilePath, - readonly streamingEnabled: boolean, - readonly sync: { - splitFilters: SplitIO.SplitFilter[], - impressionsMode: SplitIO.ImpressionsMode, - enabled: boolean, - flagSpecVersion: string, - requestOptions?: { - getHeaderOverrides?: (context: { headers: Record }) => Record - } - } - /** - * 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 - */ -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 in LogLevel]: LogLevel - } -} -/** - * User consent API - * @interface IUserConsentAPI - */ -interface IUserConsentAPI { - /** - * Sets or updates 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. - */ - setStatus(userConsent: boolean): boolean; - /** - * Gets the user consent status. - * - * @function getStatus - * @returns {ConsentStatus} The user consent status. - */ - getStatus(): SplitIO.ConsentStatus; - /** - * Consent status constants. Use this to compare with the getStatus function result. - */ - Status: { - [status in SplitIO.ConsentStatus]: SplitIO.ConsentStatus - } -} -/** - * Common settings between Browser and NodeJS settings interface. - * @interface ISharedSettings - */ -interface ISharedSettings { - /** - * Boolean value to indicate whether the logger should be enabled or disabled, or a log level string. - * - * Examples: - * ```javascript - * config.debug = true - * config.debug = 'WARN' - * ``` - * @property {boolean | LogLevel} debug - * @default false - */ - debug?: boolean | LogLevel, - /** - * 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 feature flag filters. These filters are used to fetch a subset of the feature flag 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. - * - * Example: - * `splitFilter: [ - * { type: 'byName', values: ['my_feature_flag_1', 'my_feature_flag_2'] }, // will fetch feature flags named 'my_feature_flag_1' and 'my_feature_flag_2' - * ]` - * @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', 'OPTIMIZED', and 'NONE'. - * - 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. - * - NONE: will send unique keys evaluated per feature to Split servers instead of full blown impressions, avoiding a considerable amount of traffic that impressions could generate. - * - * @property {string} impressionsMode - * @default 'OPTIMIZED' - */ - impressionsMode?: SplitIO.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 - * - * @property {boolean} enabled - * @default true - */ - 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 flag definitions. This parameter controls this polling period in seconds. - * @property {number} featuresRefreshRate - * @default 60 - */ - 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. Use `telemetryRefreshRate` instead. - */ - 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 SDK key. - * @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 instantiate. - * @property {Object} storage - */ - storage?: { - /** - * Storage type to be instantiated by the SDK. - * @property {StorageType} type - * @default 'MEMORY' - */ - type?: StorageType, - /** - * Options to be passed to the selected storage. - * @property {Object} options - */ - options?: Object, - /** - * Optional prefix to prevent any kind of data collision between SDK versions. - * @property {string} prefix - * @default 'SPLITIO' - */ - prefix?: string - }, - /** - * 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, - /** - * Mocked features file path. For testing purposes 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 EventEmitter - */ -interface IStatusInterface extends EventEmitter { - /** - * Constant object containing the SDK events for you to use. - * @property {EventConsts} Event - */ - Event: EventConsts, - /** - * Returns a promise that resolves 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, the `ready` method will return a resolved promise once the SDK is 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 { - /** - * Destroys the client instance. - * In 'standalone' mode, this method will flush any pending impressions and events, and stop the synchronization of feature flag definitions with the backend. - * In 'consumer' mode, this method will disconnect the SDK from the Redis or Pluggable storage. - * - * @function destroy - * @returns {Promise} A promise that resolves once the client is destroyed. - */ - destroy(): Promise -} -/** - * 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 - /** - * Destroys all the clients created by this factory. - * @function destroy - * @returns {Promise} - */ - destroy(): Promise -} -/****** Exposed namespace ******/ -/** - * Types and interfaces for `@splitsoftware/splitio` package for usage when integrating JavaScript SDK with TypeScript. - * For the SDK package information see {@link https://www.npmjs.com/package/@splitsoftware/splitio} - */ -declare namespace SplitIO { - /** - * Feature flag treatment value, returned by getTreatment. - * @typedef {string} Treatment - */ - type Treatment = string; - /** - * Feature flag treatment promise that resolves to actual treatment value. - * @typedef {Promise} AsyncTreatment - */ - type AsyncTreatment = Promise; - /** - * An object with the treatments for a bulk of feature flags, returned by getTreatments. For example: - * { - * feature1: 'on', - * feature2: 'off - * } - * @typedef {Object.} Treatments - */ - type Treatments = { - [featureName: string]: Treatment - }; - /** - * Feature flag treatments promise that resolves to the actual SplitIO.Treatments object. - * @typedef {Promise} AsyncTreatments - */ - type AsyncTreatments = Promise; - /** - * Feature flag evaluation result with treatment and configuration, returned by getTreatmentWithConfig. - * @typedef {Object} TreatmentWithConfig - * @property {string} treatment The treatment string - * @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. - */ - type TreatmentWithConfig = { - treatment: string, - config: string | null - }; - /** - * Feature flag treatment promise that resolves to actual treatment with config value. - * @typedef {Promise} AsyncTreatmentWithConfig - */ - type AsyncTreatmentWithConfig = Promise; - /** - * An object with the treatments with configs for a bulk of feature flags, returned by getTreatmentsWithConfig. - * Each existing configuration is a stringified version of the JSON you defined on the Split user interface. For example: - * { - * feature1: { treatment: 'on', config: null } - * feature2: { treatment: 'off', config: '{"bannerText":"Click here."}' } - * } - * @typedef {Object.} Treatments - */ - type TreatmentsWithConfig = { - [featureName: string]: TreatmentWithConfig - }; - /** - * Feature flag treatments promise that resolves to the actual SplitIO.TreatmentsWithConfig object. - * @typedef {Promise} AsyncTreatmentsWithConfig - */ - type AsyncTreatmentsWithConfig = Promise; - /** - * Possible Split SDK events. - * @typedef {string} Event - */ - type Event = 'init::timeout' | 'init::ready' | 'init::cache-ready' | 'state::update'; - /** - * Attributes should be on object with values of type string, boolean, number (dates should be sent as millis since epoch) or array of strings or numbers. - * @typedef {Object.} Attributes - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#attribute-syntax} - */ - type Attributes = { - [attributeName: string]: AttributeType - }; - /** - * Type of an attribute value - * @typedef {string | number | boolean | Array} AttributeType - */ - type AttributeType = string | number | boolean | Array; - /** - * Properties should be an object with values of type string, number, boolean or null. Size limit of ~31kb. - * @typedef {Object.} Properties - * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#track - */ - type Properties = { - [propertyName: string]: string | number | boolean | null - }; - /** - * The SplitKey object format. - * @typedef {Object.} SplitKeyObject - */ - type SplitKeyObject = { - matchingKey: string, - bucketingKey: string - }; - /** - * The customer identifier. Could be a SplitKeyObject or a string. - * @typedef {SplitKeyObject|string} SplitKey - */ - type SplitKey = SplitKeyObject | string; - /** - * Path to file with mocked features (for node). - * @typedef {string} MockedFeaturesFilePath - */ - 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 - */ - 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 - */ - 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, - sdkLanguageVersion: string - }; - /** - * Data corresponding to one feature flag view. - * @typedef {Object} SplitView - */ - type SplitView = { - /** - * The name of the feature flag. - * @property {string} name - */ - name: string, - /** - * The traffic type of the feature flag. - * @property {string} trafficType - */ - trafficType: string, - /** - * Whether the feature flag is killed or not. - * @property {boolean} killed - */ - killed: boolean, - /** - * The list of treatments available for the feature flag. - * @property {Array} treatments - */ - treatments: Array, - /** - * Current change number of the feature flag. - * @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 user interface. - * @property {Object.} configs - */ - configs: { - [treatmentName: string]: string - }, - /** - * List of sets of the feature flag. - * @property {string[]} sets - */ - sets: string[], - /** - * The default treatment of the feature flag. - * @property {string} defaultTreatment - */ - defaultTreatment: string, - }; - /** - * A promise that resolves to a feature flag view. - * @typedef {Promise} SplitView - */ - type SplitViewAsync = Promise; - /** - * An array containing the SplitIO.SplitView elements. - */ - type SplitViews = Array; - /** - * A promise that resolves to an SplitIO.SplitViews array. - * @typedef {Promise} SplitViewsAsync - */ - type SplitViewsAsync = Promise; - /** - * An array of feature flag names. - * @typedef {Array} SplitNames - */ - type SplitNames = Array; - /** - * A promise that resolves to an array of feature flag names. - * @typedef {Promise} SplitNamesAsync - */ - type SplitNamesAsync = Promise; - /** - * Synchronous storage valid types for NodeJS. - * @typedef {string} NodeSyncStorage - */ - type NodeSyncStorage = 'MEMORY'; - /** - * Asynchronous storages valid types for NodeJS. - * @typedef {string} NodeAsyncStorage - */ - type NodeAsyncStorage = 'REDIS'; - /** - * Storage valid types for the browser. - * @typedef {string} BrowserStorage - */ - type BrowserStorage = 'MEMORY' | 'LOCALSTORAGE'; - /** - * 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} - */ - interface IImpressionListener { - logImpression(data: SplitIO.ImpressionData): void - } - /** - * Available URL settings for the SDKs. - */ - type UrlSettings = { - /** - * String property to override the base URL where the SDK will get rollout plan related data, like feature flags and segments definitions. - * @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 - */ - type SplitFilterType = 'bySet' | 'byName' | 'byPrefix'; - /** - * Defines a feature flag filter, described by a type and list of values. - */ - interface SplitFilter { - /** - * Type of the filter. - * - * @property {SplitFilterType} type - */ - type: SplitFilterType, - /** - * List of values: feature flag names for 'byName' filter type, and feature flag name prefixes for 'byPrefix' type. - * - * @property {string[]} values - */ - values: string[], - } - /** - * ImpressionsMode type - * @typedef {string} ImpressionsMode - */ - type ImpressionsMode = 'OPTIMIZED' | 'DEBUG' | 'NONE'; - /** - * User consent status. - * @typedef {string} ConsentStatus - */ - type ConsentStatus = 'GRANTED' | 'DECLINED' | 'UNKNOWN'; - /** - * 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} - */ - 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 flag definitions. This parameter controls this polling period in seconds. - * @property {number} featuresRefreshRate - * @default 60 - */ - 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. Use `telemetryRefreshRate` instead. - */ - 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/360020448791-JavaScript-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 SDK key. - * @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, - /** - * 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 purposes 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?: MockedFeaturesMap, - /** - * Defines which kind of storage we can instantiate on the browser. - * Possible storage types are 'MEMORY', which is the default, and 'LOCALSTORAGE'. - * @property {Object} storage - */ - storage?: { - /** - * Storage type to be instantiated by the SDK. - * @property {BrowserStorage} type - * @default 'MEMORY' - */ - type?: BrowserStorage, - /** - * Optional prefix to prevent any kind of data collision between SDK versions. - * @property {string} prefix - * @default 'SPLITIO' - */ - prefix?: string - }, - /** - * 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, - /** - * User consent status. Possible values are `'GRANTED'`, which is the default, `'DECLINED'` or `'UNKNOWN'`. - * - `'GRANTED'`: the user grants consent for tracking events and impressions. The SDK sends them to Split cloud. - * - `'DECLINED'`: the user declines consent for tracking events and impressions. The SDK does not send them to Split cloud. - * - `'UNKNOWN'`: the user neither grants nor declines consent for tracking events and impressions. The SDK tracks them in its internal storage, and eventually either sends - * them or not if the consent status is updated to 'GRANTED' or 'DECLINED' respectively. The status can be updated at any time with the `UserConsent.setStatus` factory method. - * - * @typedef {string} userConsent - * @default 'GRANTED' - */ - userConsent?: ConsentStatus, - sync?: ISharedSettings['sync'] & { - /** - * Custom options object for HTTP(S) requests in the Browser. - * If provided, this object is merged with the options object passed by the SDK for EventSource and Fetch calls. - */ - requestOptions?: { - /** - * Custom function called before each request, allowing you to add or update headers in SDK HTTP requests. - * Some headers, such as `SplitSDKVersion`, are required by the SDK and cannot be overridden. - * To pass multiple headers with the same name, combine their values into a single line, separated by commas. Example: `{ 'Authorization': 'value1, value2' }` - * Or provide keys with different case since headers are case-insensitive. Example: `{ 'authorization': 'value1', 'Authorization': 'value2' }` - * - * NOTE: to pass custom headers to the streaming connection in Browser, you should polyfill the `window.EventSource` object with a library that supports headers, - * like https://www.npmjs.com/package/event-source-polyfill, since native EventSource does not support them and will be ignored. - * - * @property getHeaderOverrides - * @default undefined - * - * @param context - The context for the request. - * @param context.headers - The current headers in the request. - * @returns A set of headers to be merged with the current headers. - * - * @example - * const getHeaderOverrides = (context) => { - * return { - * 'Authorization': context.headers['Authorization'] + ', other-value', - * 'custom-header': 'custom-value' - * }; - * }; - */ - getHeaderOverrides?: (context: { headers: Record }) => Record - }, - } - } - /** - * 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} - */ - 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 can instantiate on NodeJS for 'standalone' mode. - * The only possible storage type is 'MEMORY', which is the default. - * @property {Object} storage - */ - storage?: { - /** - * Synchronous storage type to be instantiated by the SDK. - * @property {NodeSyncStorage} type - * @default 'MEMORY' - */ - type?: NodeSyncStorage, - /** - * Optional prefix to prevent any kind of data collision between SDK versions. - * @property {string} prefix - * @default 'SPLITIO' - */ - prefix?: string - }, - /** - * The SDK mode. When using the default 'MEMORY' storage, the only possible value is "standalone", which is the default. - * For "localhost" mode, use "localhost" as authorizationKey. - * - * @property {'standalone'} mode - * @default 'standalone' - */ - mode?: 'standalone' - sync?: INodeBasicSettings['sync'] & { - /** - * Custom options object for HTTP(S) requests in NodeJS. - * If provided, this object is merged with the options object passed by the SDK for EventSource and Node-Fetch calls. - * @see {@link https://www.npmjs.com/package/node-fetch#options} - */ - requestOptions?: { - /** - * Custom function called before each request, allowing you to add or update headers in SDK HTTP requests. - * Some headers, such as `SplitSDKVersion`, are required by the SDK and cannot be overridden. - * To pass multiple headers with the same name, combine their values into a single line, separated by commas. Example: `{ 'Authorization': 'value1, value2' }` - * Or provide keys with different case since headers are case-insensitive. Example: `{ 'authorization': 'value1', 'Authorization': 'value2' }` - * - * @property getHeaderOverrides - * @default undefined - * - * @param context - The context for the request. - * @param context.headers - The current headers in the request. - * @returns A set of headers to be merged with the current headers. - * - * @example - * const getHeaderOverrides = (context) => { - * return { - * 'Authorization': context.headers['Authorization'] + ', other-value', - * 'custom-header': 'custom-value' - * }; - * }; - */ - getHeaderOverrides?: (context: { headers: Record }) => Record - /** - * Custom NodeJS HTTP(S) Agent used by the SDK for HTTP(S) requests. - * - * You can use it, for example, for certificate pinning or setting a network proxy: - * - * ```javascript - * const { HttpsProxyAgent } = require('https-proxy-agent'); - * - * const proxyAgent = new HttpsProxyAgent(process.env.HTTPS_PROXY || 'http://10.10.1.10:1080'); - * - * const factory = SplitFactory({ - * ... - * sync: { - * requestOptions: { - * agent: proxyAgent - * } - * } - * }) - * ``` - * - * @see {@link https://nodejs.org/api/https.html#class-httpsagent} - * - * @property {http.Agent | https.Agent} agent - * @default undefined - */ - agent?: RequestOptions["agent"] - }, - } - } - /** - * 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.INodeSettings instead. - * @interface INodeAsyncSettings - * @extends INodeBasicSettings - * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} - */ - interface INodeAsyncSettings extends INodeBasicSettings { - /** - * Defines which kind of async storage we can instantiate on NodeJS for 'consumer' mode. - * The only possible storage type is 'REDIS'. - * @property {Object} storage - */ - storage: { - /** - * 'REDIS' storage type to be instantiated by the SDK. - * @property {NodeAsyncStorage} type - */ - type: NodeAsyncStorage, - /** - * Options to be passed to the Redis storage. Use it with storage type: 'REDIS'. - * @property {Object} options - */ - options?: { - /** - * Redis URL. If set, `host`, `port`, `db` and `pass` params will be ignored. - * - * Examples: - * ``` - * url: 'localhost' - * url: '127.0.0.1:6379' - * url: 'redis://:authpassword@127.0.0.1:6379/0' - * ``` - * @property {string=} url - */ - url?: string, - /** - * Redis host. - * @property {string=} host - * @default 'localhost' - */ - host?: string, - /** - * Redis port. - * @property {number=} port - * @default 6379 - */ - port?: number, - /** - * Redis database to be used. - * @property {number=} db - * @default 0 - */ - db?: number, - /** - * Redis password. Don't define if no password is used. - * @property {string=} pass - * @default undefined - */ - pass?: string, - /** - * The milliseconds before a timeout occurs during the initial connection to the Redis server. - * @property {number=} connectionTimeout - * @default 10000 - */ - connectionTimeout?: number, - /** - * The milliseconds before Redis commands are timeout by the SDK. - * Method calls that involve Redis commands, like `client.getTreatment` or `client.track` calls, are resolved when the commands success or timeout. - * @property {number=} operationTimeout - * @default 5000 - */ - operationTimeout?: number, - /** - * TLS configuration for Redis connection. - * @see {@link https://www.npmjs.com/package/ioredis#tls-options } - * - * @property {Object=} tls - * @default undefined - */ - tls?: RedisOptions['tls'], - }, - /** - * Optional prefix to prevent any kind of data collision between SDK versions. - * @property {string} prefix - * @default 'SPLITIO' - */ - prefix?: string - }, - /** - * The SDK mode. When using 'REDIS' storage type, the only possible value is "consumer", which is required. - * - * @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#state-sharing-redis-integration} - * - * @property {'consumer'} mode - */ - mode: 'consumer' - } - /** - * This represents the interface for the SDK instance with synchronous storage. - * @interface ISDK - * @extends IBasicSDK - */ - interface ISDK extends IBasicSDK { - /** - * Returns the default 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 SDK instance with synchronous storage. - * @interface IBrowserSDK - * @extends IBasicSDK - */ - interface IBrowserSDK extends IBasicSDK { - /** - * Returns the default client instance of the SDK. - * @function client - * @returns {IBrowserClient} The client instance. - */ - client(): IBrowserClient, - /** - * Returns a shared client of the SDK. - * @function client - * @param {SplitKey} key The key for the new client instance. - * @returns {IBrowserClient} The client instance. - */ - client(key: SplitKey): IBrowserClient - /** - * Returns a manager instance of the SDK to explore available information. - * @function manager - * @returns {IManager} The manager instance. - */ - manager(): IManager, - /** - * User consent API. - * @property UserConsent - */ - UserConsent: IUserConsentAPI - } - /** - * This represents the interface for the SDK instance with asynchronous storage. - * @interface IAsyncSDK - * @extends IBasicSDK - */ - 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 instance on server-side, where the user key is not bound to the instance and must be provided on each method call. - * This interface is available in NodeJS, or when importing the 'server' sub-package (e.g., `import { SplitFactory } from '@splitsoftware/splitio/server'`). - * - * @interface IClient - * @extends IBasicClient - */ - interface IClient extends IBasicClient { - /** - * Returns a Treatment value, which is the treatment string for the given feature. - * - * @function getTreatment - * @param {string} key - The string key representing the consumer. - * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatment} The treatment string. - */ - getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes): Treatment, - /** - * Returns a TreatmentWithConfig value, which is an object with both treatment and config string for the given feature. - * - * @function getTreatmentWithConfig - * @param {string} key - The string key representing the consumer. - * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {TreatmentWithConfig} The TreatmentWithConfig, the object containing the treatment string and the - * configuration stringified JSON (or null if there was no config for that treatment). - */ - getTreatmentWithConfig(key: SplitKey, featureFlagName: string, attributes?: Attributes): TreatmentWithConfig, - /** - * Returns a Treatments value, which is an object map with the treatments for the given features. - * - * @function getTreatments - * @param {string} key - The string key representing the consumer. - * @param {Array} featureFlagNames - An array of the feature flag names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The treatments object map. - */ - getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the given features. - * - * @function getTreatmentsWithConfig - * @param {string} key - The string key representing the consumer. - * @param {Array} featureFlagNames - An array of the feature flag names we want 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, featureFlagNames: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. - * - * @function getTreatmentsByFlagSet - * @param {string} key - The string key representing the consumer. - * @param {string} flagSet - The flag set name we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The map with all the Treatments objects - */ - getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag set. - * - * @function getTreatmentsWithConfigByFlagSet - * @param {string} key - The string key representing the consumer. - * @param {string} flagSet - The flag set name we want 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 - */ - getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): TreatmentsWithConfig, - /** - * Returns a Returns a Treatments value, which is an object with both treatment and config string for to the feature flags related to the given flag sets. - * - * @function getTreatmentsByFlagSets - * @param {string} key - The string key representing the consumer. - * @param {Array} flagSets - An array of the flag set names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The map with all the Treatments objects - */ - getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag sets. - * - * @function getTreatmentsWithConfigByFlagSets - * @param {string} key - The string key representing the consumer. - * @param {Array} flagSets - An array of the flag set names we want 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 - */ - getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Tracks an event to be fed to the results product on Split user interface. - * - * @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. See {@link https://help.split.io/hc/en-us/articles/360019916311-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 successfully or not. - */ - track(key: SplitIO.SplitKey, trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, - } - /** - * This represents the interface for the Client instance on client-side, where the user key is bound to the instance on creation and does not need to be provided on each method call. - * This interface is the default when importing the SDK in the Browser, or when importing the 'client' sub-package (e.g., `import { SplitFactory } from '@splitsoftware/splitio/client'`). - * - * @interface IBrowserClient - * @extends IBasicClient - */ - interface IBrowserClient extends IBasicClient { - /** - * Returns a Treatment value, which is the treatment string for the given feature. - * - * @function getTreatment - * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatment} The treatment string. - */ - getTreatment(featureFlagName: string, attributes?: Attributes): Treatment, - /** - * Returns a TreatmentWithConfig value, which an object with both treatment and config string for the given feature. - * - * @function getTreatmentWithConfig - * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {TreatmentWithConfig} The TreatmentWithConfig, the object containing the treatment string and the - * configuration stringified JSON (or null if there was no config for that treatment). - */ - getTreatmentWithConfig(featureFlagName: string, attributes?: Attributes): TreatmentWithConfig, - /** - * Returns a Treatments value, which is an object map with the treatments for the given features. - * - * @function getTreatments - * @param {Array} featureFlagNames - An array of the feature flags names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The treatments object map. - */ - getTreatments(featureFlagNames: string[], attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the given features. - * - * @function getTreatmentsWithConfig - * @param {Array} featureFlagNames - An array of the feature flag names we want 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(featureFlagNames: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. - * - * @function getTreatmentsByFlagSet - * @param {string} flagSet - The flag set name we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The map with all the Treatments objects - */ - getTreatmentsByFlagSet(flagSet: string, attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag set. - * - * @function getTreatmentsWithConfigByFlagSet - * @param {string} flagSet - The flag set name we want 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 - */ - getTreatmentsWithConfigByFlagSet(flagSet: string, attributes?: Attributes): TreatmentsWithConfig, - /** - * Returns a Returns a Treatments value, which is an object with both treatment and config string for to the feature flags related to the given flag sets. - * - * @function getTreatmentsByFlagSets - * @param {Array} flagSets - An array of the flag set names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {Treatments} The map with all the Treatments objects - */ - getTreatmentsByFlagSets(flagSets: string[], attributes?: Attributes): Treatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag sets. - * - * @function getTreatmentsWithConfigByFlagSets - * @param {Array} flagSets - An array of the flag set names we want 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 - */ - getTreatmentsWithConfigByFlagSets(flagSets: string[], attributes?: Attributes): TreatmentsWithConfig, - /** - * Tracks an event to be fed to the results product on Split user interface. - * - * @function track - * @param {string} trafficType - The traffic type of the entity related to this event. See {@link https://help.split.io/hc/en-us/articles/360019916311-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 successfully or not. - */ - track(trafficType: string, eventType: string, value?: number, properties?: Properties): boolean, - /** - * Add an attribute to client's in memory attributes storage. - * - * @param {string} attributeName Attribute name - * @param {AttributeType} attributeValue Attribute value - * @returns {boolean} true if the attribute was stored and false otherwise - */ - setAttribute(attributeName: string, attributeValue: AttributeType): boolean, - /** - * Returns the attribute with the given name. - * - * @param {string} attributeName Attribute name - * @returns {AttributeType} Attribute with the given name - */ - getAttribute(attributeName: string): AttributeType, - /** - * Removes from client's in memory attributes storage the attribute with the given name. - * - * @param {string} attributeName - * @returns {boolean} true if attribute was removed and false otherwise - */ - removeAttribute(attributeName: string): boolean, - /** - * 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 - */ - setAttributes(attributes: Attributes): boolean, - /** - * Return all the attributes stored in client's in memory attributes storage. - * - * @returns {Attributes} returns all the stored attributes - */ - getAttributes(): Attributes, - /** - * Remove all the stored attributes in the client's in memory attribute storage. - * - * @returns {boolean} true if all attribute were removed and false otherwise - */ - clearAttributes(): boolean - } - /** - * This represents the interface for the Client instance on server-side with asynchronous storage, like REDIS. - * User key is not bound to the instance and must be provided on each method call, which returns a promise. - * This interface is available in NodeJS, or when importing the 'server' sub-package (e.g., `import { SplitFactory } from '@splitsoftware/splitio/server'`). - * - * @interface IAsyncClient - * @extends IBasicClient - */ - interface IAsyncClient 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} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatment} Treatment promise that resolves to the treatment string. - */ - getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes): AsyncTreatment, - /** - * Returns a TreatmentWithConfig value, which will be (or eventually be) an object with both treatment and config string for the given feature. - * - * @function getTreatmentWithConfig - * @param {string} key - The string key representing the consumer. - * @param {string} featureFlagName - The string that represents the feature flag we want to get the treatment. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatmentWithConfig} TreatmentWithConfig promise that resolves to the TreatmentWithConfig object. - */ - getTreatmentWithConfig(key: SplitKey, featureFlagName: string, attributes?: Attributes): AsyncTreatmentWithConfig, - /** - * Returns a Treatments value, which will be (or eventually be) an object map with the treatments for the given features. - * - * @function getTreatments - * @param {string} key - The string key representing the consumer. - * @param {Array} featureFlagNames - An array of the feature flag names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatments} Treatments promise that resolves to the treatments object map. - */ - getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): AsyncTreatments, - /** - * Returns a TreatmentsWithConfig value, which will be (or eventually be) an object map with the TreatmentWithConfig (an object with both treatment and config string) for the given features. - * - * @function getTreatmentsWithConfig - * @param {string} key - The string key representing the consumer. - * @param {Array} featureFlagNames - An array of the feature flag names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatmentsWithConfig} TreatmentsWithConfig promise that resolves to the map of TreatmentsWithConfig objects. - */ - getTreatmentsWithConfig(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): AsyncTreatmentsWithConfig, - /** - * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. - * - * @function getTreatmentsByFlagSet - * @param {string} key - The string key representing the consumer. - * @param {string} flagSet - The flag set name we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatments} Treatments promise that resolves to the treatments object map. - */ - getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): AsyncTreatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag set. - * - * @function getTreatmentsWithConfigByFlagSet - * @param {string} flagSet - The flag set name we want to get the treatments. - * @param {string} key - The string key representing the consumer. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatmentsWithConfig} TreatmentsWithConfig promise that resolves to the TreatmentsWithConfig object. - */ - getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): AsyncTreatmentsWithConfig, - /** - * Returns a Returns a Treatments value, which is an object with both treatment and config string for to the feature flags related to the given flag sets. - * - * @function getTreatmentsByFlagSets - * @param {string} key - The string key representing the consumer. - * @param {Array} flagSets - An array of the flag set names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatments} Treatments promise that resolves to the treatments object map. - */ - getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): AsyncTreatments, - /** - * Returns a TreatmentsWithConfig value, which is an object map with the TreatmentWithConfig (an object with both treatment and config string) for the feature flags related to the given flag sets. - * - * @function getTreatmentsWithConfigByFlagSets - * @param {string} key - The string key representing the consumer. - * @param {Array} flagSets - An array of the flag set names we want to get the treatments. - * @param {Attributes=} attributes - An object of type Attributes defining the attributes for the given key. - * @returns {AsyncTreatmentsWithConfig} TreatmentsWithConfig promise that resolves to the TreatmentsWithConfig object. - */ - getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): AsyncTreatmentsWithConfig, - /** - * Tracks an event to be fed to the results product on Split user interface, 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. See {@link https://help.split.io/hc/en-us/articles/360019916311-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 {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 - } - /** - * Representation of a manager instance with synchronous storage of the SDK. - * @interface IManager - * @extends IStatusInterface - */ - interface IManager extends IStatusInterface { - /** - * Get the array of feature flag names. - * @function names - * @returns {SplitNames} The list of feature flag names. - */ - names(): SplitNames; - /** - * Get the array of feature flags data in SplitView format. - * @function splits - * @returns {SplitViews} The list of SplitIO.SplitView. - */ - splits(): SplitViews; - /** - * Get the data of a feature flag in SplitView format. - * @function split - * @param {string} featureFlagName The name of the feature flag we want to get info of. - * @returns {SplitView | null} The SplitIO.SplitView of the given feature flag name or null if the feature flag is not found. - */ - split(featureFlagName: string): SplitView | null; - } - /** - * Representation of a manager instance with asynchronous storage of the SDK. - * @interface IAsyncManager - * @extends IStatusInterface - */ - interface IAsyncManager extends IStatusInterface { - /** - * Get the array of feature flag names. - * @function names - * @returns {SplitNamesAsync} A promise that resolves to the list of feature flag names. - */ - names(): SplitNamesAsync; - /** - * Get the array of feature flags data in SplitView format. - * @function splits - * @returns {SplitViewsAsync} A promise that resolves to the SplitIO.SplitView list. - */ - splits(): SplitViewsAsync; - /** - * Get the data of a feature flag in SplitView format. - * @function split - * @param {string} featureFlagName The name of the feature flag we want to get info of. - * @returns {SplitViewAsync} A promise that resolves to the SplitIO.SplitView value. - */ - split(featureFlagName: string): SplitViewAsync; - } -} From 194e58a84c470f88d7c653a3203b191a5221b00a Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Sat, 26 Oct 2024 12:37:56 -0300 Subject: [PATCH 13/20] Update changelog entry --- CHANGES.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 4d6b2a445..c5b3767f4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,12 +5,10 @@ - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. - BREAKING CHANGES: - Dropped support for NodeJS v6. The SDK now requires NodeJS v14 or above. + - Renamed some TypeScript definitions in the SplitIO namespace to avoid conflicts with other libraries: `ISDK` to `INodeSDK`, `IAsyncSDK` to `INodeAsyncSDK`, `IBrowserSDK` to `ISDK`, `IClient` to `INodeClient`, `IAsyncClient` to `INodeAsyncClient`, `IBrowserClient` to `IClient`. - Removed internal ponyfills for the `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 provide a polyfill. - Removed the deprecated `GOOGLE_ANALYTICS_TO_SPLIT` and `SPLIT_TO_GOOGLE_ANALYTICS` integrations. The `integrations` configuration option has been removed from the SDK factory configuration, along with the associated interfaces in the TypeScript definitions. - Removed the `core.trafficType` configuration option (`SplitIO.IBrowserSettings['core']['trafficType]`) and the `trafficType` parameter from the SDK `client()` method in Browser (`SplitIO.IBrowserSDK['client']`). As a result, traffic types can no longer be bound to SDK clients, and the traffic type must be provided in the `track` method. - - TypeScript definitions: - - Removed an overloaded `client` method in the `SplitIO.ISDK` interface that accepted `key` and `trafficType` parameters. This interface corresponds to the SDK factory instance in NodeJS, which, unlike `SplitIO.IBrowserSDK` for the Browser, does not handle multiple client instances based on keys. - - Updated the `SplitIO.IBrowserSDK` and `SplitIO.IBrowserClient` interfaces to no longer extend the `SplitIO.ISDK` and `SplitIO.IClient` interfaces respectively, as the SDK factory instance in NodeJS or server-side (`SplitIO.ISDK`) has a different API than the SDK client instance in the Browser or client-side (`SplitIO.IBrowserClient`). 10.28.0 (September 6, 2024) - Updated @splitsoftware/splitio-commons package to version 1.17.0 that includes minor updates: From 93d807e2e6c6719782f528cbec5a05450c9c3bb8 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 28 Oct 2024 13:01:55 -0300 Subject: [PATCH 14/20] Update eslint config --- .eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 1d7f59384..b410eddeb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -46,7 +46,7 @@ ], "rules": { "no-restricted-syntax": ["error", "ForOfStatement", "ForInStatement", "ArrayPattern"], - "compat/compat": ["error", "defaults, ie 10, node 6"], + "compat/compat": ["error", "defaults, node >=14"], "no-throw-literal": "error", "import/no-default-export": "error", "import/no-self-import": "error" From e2f1b71ad71a44e89c21277aff80e639e25911b5 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 29 Oct 2024 13:51:53 -0300 Subject: [PATCH 15/20] Update JS-commons and prepare rc --- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- src/settings/defaults/version.js | 2 +- ts-tests/index.ts | 15 +-------------- 4 files changed, 13 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5024d5fc6..5e7c259f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.3", + "version": "11.0.0-rc.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.3", + "version": "11.0.0-rc.4", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.4", + "@splitsoftware/splitio-commons": "2.0.0-rc.5", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -869,9 +869,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.4.tgz", - "integrity": "sha512-z0rm4X9oh7LdIcHeEkh6Ca3JzfdhJ0IH3r7nZ6ghL0AXmPzbezoDswxjKOe/WYBbTW3utsgLqTTjr9Ww/b/hUw==", + "version": "2.0.0-rc.5", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.5.tgz", + "integrity": "sha512-hNLA3cfVj5yGSHpOyTQVzcU2kIceJtJOdatcuue2ENOesjwDHfpvEy/YkIgLcLwXpvUxTFKpZd1BRej8gSbWoA==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -8587,9 +8587,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.4.tgz", - "integrity": "sha512-z0rm4X9oh7LdIcHeEkh6Ca3JzfdhJ0IH3r7nZ6ghL0AXmPzbezoDswxjKOe/WYBbTW3utsgLqTTjr9Ww/b/hUw==", + "version": "2.0.0-rc.5", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.5.tgz", + "integrity": "sha512-hNLA3cfVj5yGSHpOyTQVzcU2kIceJtJOdatcuue2ENOesjwDHfpvEy/YkIgLcLwXpvUxTFKpZd1BRej8gSbWoA==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 6d564c8b1..3a73c4a9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.3", + "version": "11.0.0-rc.4", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.4", + "@splitsoftware/splitio-commons": "2.0.0-rc.5", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 818b1f165..36355d51c 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.0.0-rc.3'; +export const packageVersion = '11.0.0-rc.4'; diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 1cbe834ea..226c17626 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -594,23 +594,9 @@ let fullAsyncSettings: SplitIO.INodeAsyncSettings = { labelsEnabled: false, IPAddressesEnabled: false }, - scheduler: { - featuresRefreshRate: 1, - impressionsRefreshRate: 1, - impressionsQueueSize: 1, - metricsRefreshRate: 1, - telemetryRefreshRate: 1, - segmentsRefreshRate: 1, - offlineRefreshRate: 1, - eventsPushRate: 1, - eventsQueueSize: 1 - }, startup: { readyTimeout: 1, - requestTimeoutBeforeReady: 1, - retriesOnFailureBeforeReady: 1 }, - features: mockedFeaturesPath, storage: { type: 'REDIS', options: { @@ -630,6 +616,7 @@ let fullAsyncSettings: SplitIO.INodeAsyncSettings = { debug: true, sync: { splitFilters: splitFilters, + impressionsMode: 'DEBUG', } }; From e0229c4555ce972f4f480210d11e69f71fee351e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 30 Oct 2024 18:02:14 -0300 Subject: [PATCH 16/20] rc in CDN --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d28295fdb..6d498d43d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/refactor_type_definitions' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/refactor_type_definitions' }} strategy: matrix: environment: diff --git a/CHANGES.txt b/CHANGES.txt index c5b3767f4..d881aa7f5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,7 +2,7 @@ - Added support for targeting rules based on large segments for browsers. - Added `factory.destroy()` method, which invokes the `destroy` method of all clients created by the factory. - Updated @splitsoftware/splitio-commons package to version 2.0.0 that includes major updates and updated some transitive dependencies for vulnerability fixes. - - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for EcmaScript Modules build. + - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for ECMAScript Modules build. - BREAKING CHANGES: - Dropped support for NodeJS v6. The SDK now requires NodeJS v14 or above. - Renamed some TypeScript definitions in the SplitIO namespace to avoid conflicts with other libraries: `ISDK` to `INodeSDK`, `IAsyncSDK` to `INodeAsyncSDK`, `IBrowserSDK` to `ISDK`, `IClient` to `INodeClient`, `IAsyncClient` to `INodeAsyncClient`, `IBrowserClient` to `IClient`. From 7945e0067f65af9429c4bff80ad1883d7bdca861 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 31 Oct 2024 00:32:49 -0300 Subject: [PATCH 17/20] Update ts test --- ts-tests/index.ts | 206 +++++++++++++++++++++++++--------------------- types/index.d.ts | 6 +- 2 files changed, 113 insertions(+), 99 deletions(-) diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 226c17626..562b95b91 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -25,19 +25,19 @@ let trackPromise: Promise; /**** Interfaces ****/ // Facade return interface -let NodeSDK: SplitIO.INodeSDK; -let AsyncSDK: SplitIO.INodeAsyncSDK; -let BrowserSDK: SplitIO.ISDK; +let SDK: SplitIO.ISDK; +let AsyncSDK: SplitIO.IAsyncSDK; +let BrowserSDK: SplitIO.IBrowserSDK; // Settings interfaces let nodeSettings: SplitIO.INodeSettings; let asyncSettings: SplitIO.INodeAsyncSettings; let browserSettings: SplitIO.IBrowserSettings; // Client & Manager APIs -let nodeClient: SplitIO.INodeClient; +let client: SplitIO.IClient; let manager: SplitIO.IManager; -let nodeAsyncClient: SplitIO.INodeAsyncClient; +let asyncClient: SplitIO.IAsyncClient; let asyncManager: SplitIO.IAsyncManager; -let browserClient: SplitIO.IClient; +let browserClient: SplitIO.IBrowserClient; // Utility interfaces let impressionListener: SplitIO.IImpressionListener; @@ -137,7 +137,7 @@ splitViewsAsync = splitViewsPromise; splitKey = 'someKey'; splitKey = splitKeyObj; -/**** Tests for INodeSDK interface ****/ +/**** Tests for ISDK interface ****/ // For node with sync storage nodeSettings = { @@ -162,8 +162,8 @@ browserSettings = { key: 'customer-key' } }; -// With sync settings should return INodeSDK, if settings have async storage it should return INodeAsyncSDK -NodeSDK = SplitFactory(nodeSettings); +// With sync settings should return ISDK, if settings have async storage it should return IAsyncSDK +SDK = SplitFactory(nodeSettings); AsyncSDK = SplitFactory(asyncSettings); BrowserSDK = SplitFactory(browserSettings); @@ -173,38 +173,38 @@ const instantiatedSettingsCore: { key: SplitIO.SplitKey, labelsEnabled: boolean, IPAddressesEnabled: boolean -} = NodeSDK.settings.core; -const instantiatedSettingsMode: ('standalone' | 'consumer' | 'consumer_partial' | 'localhost') = NodeSDK.settings.mode; -const instantiatedSettingsScheduler: { [key: string]: number } = NodeSDK.settings.scheduler; -const instantiatedSettingsStartup: { [key: string]: number } = NodeSDK.settings.startup; -const instantiatedSettingsStorage = NodeSDK.settings.storage as SplitIO.StorageOptions; -const instantiatedSettingsUrls: { [key: string]: string } = NodeSDK.settings.urls; -const instantiatedSettingsVersion: string = NodeSDK.settings.version; -let instantiatedSettingsFeatures = NodeSDK.settings.features as SplitIO.MockedFeaturesMap; +} = SDK.settings.core; +const instantiatedSettingsMode: ('standalone' | 'consumer' | 'consumer_partial' | 'localhost') = SDK.settings.mode; +const instantiatedSettingsScheduler: { [key: string]: number } = SDK.settings.scheduler; +const instantiatedSettingsStartup: { [key: string]: number } = SDK.settings.startup; +const instantiatedSettingsStorage = SDK.settings.storage as SplitIO.StorageOptions; +const instantiatedSettingsUrls: { [key: string]: string } = SDK.settings.urls; +const instantiatedSettingsVersion: string = SDK.settings.version; +let instantiatedSettingsFeatures = SDK.settings.features as SplitIO.MockedFeaturesMap; // We should be able to write on features prop. The rest are readonly props. instantiatedSettingsFeatures.something = 'something'; -NodeSDK.settings.features = 'new_file_path'; // Node -NodeSDK.settings.features = { 'split_x': 'on' }; // Browser +SDK.settings.features = 'new_file_path'; // Node +SDK.settings.features = { 'split_x': 'on' }; // Browser // Client and Manager -nodeClient = NodeSDK.client(); -manager = NodeSDK.manager(); +client = SDK.client(); +manager = SDK.manager(); manager = BrowserSDK.manager(); // Today async clients are only possible on Node. Shared client creation not available here. -nodeAsyncClient = AsyncSDK.client(); +asyncClient = AsyncSDK.client(); asyncManager = AsyncSDK.manager(); // Browser client for attributes binding browserClient = BrowserSDK.client(); browserClient = BrowserSDK.client('a customer key'); // Logger -NodeSDK.Logger.enable(); -NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.DEBUG); -NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.INFO); -NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.WARN); -NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.ERROR); -NodeSDK.Logger.setLogLevel(NodeSDK.Logger.LogLevel.NONE); -NodeSDK.Logger.disable(); +SDK.Logger.enable(); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.DEBUG); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.INFO); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.WARN); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.ERROR); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.NONE); +SDK.Logger.disable(); AsyncSDK.Logger.enable(); AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.DEBUG); @@ -217,163 +217,163 @@ AsyncSDK.Logger.disable(); /**** Tests for IClient interface ****/ // Events constants we get -const eventConsts: { [key: string]: SplitIO.Event } = nodeClient.Event; -splitEvent = nodeClient.Event.SDK_READY; -splitEvent = nodeClient.Event.SDK_READY_FROM_CACHE; -splitEvent = nodeClient.Event.SDK_READY_TIMED_OUT; -splitEvent = nodeClient.Event.SDK_UPDATE; +const eventConsts: { [key: string]: SplitIO.Event } = client.Event; +splitEvent = client.Event.SDK_READY; +splitEvent = client.Event.SDK_READY_FROM_CACHE; +splitEvent = client.Event.SDK_READY_TIMED_OUT; +splitEvent = client.Event.SDK_UPDATE; // Client implements methods from NodeJS.Events. Testing a few. -nodeClient = nodeClient.on(splitEvent, () => { }); -const a: boolean = nodeClient.emit(splitEvent); -nodeClient = nodeClient.removeAllListeners(splitEvent); -nodeClient = nodeClient.removeAllListeners(); -const b: number = nodeClient.listenerCount(splitEvent); -let nodeEventEmitter: NodeJS.EventEmitter = nodeClient; +client = client.on(splitEvent, () => { }); +const a: boolean = client.emit(splitEvent); +client = client.removeAllListeners(splitEvent); +client = client.removeAllListeners(); +const b: number = client.listenerCount(splitEvent); +let nodeEventEmitter: NodeJS.EventEmitter = client; // Ready, destroy and flush -let promise: Promise = nodeClient.ready(); -promise = nodeClient.destroy(); -promise = NodeSDK.destroy(); +let promise: Promise = client.ready(); +promise = client.destroy(); +promise = SDK.destroy(); // @TODO not public yet -// promise = nodeClient.flush(); +// promise = client.flush(); // We can call getTreatment with or without a key. -treatment = nodeClient.getTreatment(splitKey, 'mySplit'); +treatment = client.getTreatment(splitKey, 'mySplit'); treatment = browserClient.getTreatment('mySplit'); // Attributes parameter is optional on both signatures. -treatment = nodeClient.getTreatment(splitKey, 'mySplit', attributes); +treatment = client.getTreatment(splitKey, 'mySplit', attributes); treatment = browserClient.getTreatment('mySplit', attributes); // We can call getTreatments with or without a key. -treatments = nodeClient.getTreatments(splitKey, ['mySplit']); +treatments = client.getTreatments(splitKey, ['mySplit']); treatments = browserClient.getTreatments(['mySplit']); // Attributes parameter is optional on both signatures. -treatments = nodeClient.getTreatments(splitKey, ['mySplit'], attributes); +treatments = client.getTreatments(splitKey, ['mySplit'], attributes); treatments = browserClient.getTreatments(['mySplit'], attributes); // We can call getTreatmentWithConfig with or without a key. -treatmentWithConfig = nodeClient.getTreatmentWithConfig(splitKey, 'mySplit'); +treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit'); treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit'); // Attributes parameter is optional on both signatures. -treatmentWithConfig = nodeClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); +treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit', attributes); treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit', attributes); // We can call getTreatmentsWithConfig with or without a key. -treatmentsWithConfig = nodeClient.getTreatmentsWithConfig(splitKey, ['mySplit']); +treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit']); treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit']); // Attributes parameter is optional on both signatures. -treatmentsWithConfig = nodeClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); +treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit'], attributes); // We can call getTreatmentsByFlagSet with or without a key. -treatments = nodeClient.getTreatmentsByFlagSet(splitKey, 'set_a'); +treatments = client.getTreatmentsByFlagSet(splitKey, 'set_a'); treatments = browserClient.getTreatmentsByFlagSet('set_a'); // Attributes parameter is optional. -treatments = nodeClient.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); +treatments = client.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); treatments = browserClient.getTreatmentsByFlagSet('set_a', attributes); // We can call getTreatmentsByFlagSets with or without a key. -treatments = nodeClient.getTreatmentsByFlagSets(splitKey, ['set_a']); +treatments = client.getTreatmentsByFlagSets(splitKey, ['set_a']); treatments = browserClient.getTreatmentsByFlagSets(['set_a']); // Attributes parameter is optional. -treatments = nodeClient.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); +treatments = client.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); treatments = browserClient.getTreatmentsByFlagSets(['set_a'], attributes); // We can call getTreatmentsWithConfigByFlagSet with or without a key. -treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); +treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSet('set_a'); // Attributes parameter is optional. -treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); +treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSet('set_a', attributes); // We can call getTreatmentsWithConfigByFlagSets with or without a key. -treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); +treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSets(['set_a']); // Attributes parameter is optional. -treatmentsWithConfig = nodeClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); +treatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); treatmentsWithConfig = browserClient.getTreatmentsWithConfigByFlagSets(['set_a'], attributes); // We can call track with or without a key. -tracked = nodeClient.track(splitKey, 'myTrafficType', 'myEventType'); // all params +tracked = client.track(splitKey, 'myTrafficType', 'myEventType'); // all params tracked = browserClient.track('myTrafficType', 'myEventType'); // key bound, tt provided. // Value parameter is optional on all signatures. -tracked = nodeClient.track(splitKey, 'myTrafficType', 'myEventType', 10); +tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10); tracked = browserClient.track('myTrafficType', 'myEventType', 10); // Properties parameter is optional on all signatures. -tracked = nodeClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); +tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); tracked = browserClient.track('myTrafficType', 'myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); /*** Repeating tests for Async Client ***/ // Events constants we get (same as for sync client, just for interface checking) -const eventConstsAsync: { [key: string]: SplitIO.Event } = nodeAsyncClient.Event; -splitEvent = nodeAsyncClient.Event.SDK_READY; -splitEvent = nodeAsyncClient.Event.SDK_READY_FROM_CACHE; -splitEvent = nodeAsyncClient.Event.SDK_READY_TIMED_OUT; -splitEvent = nodeAsyncClient.Event.SDK_UPDATE; +const eventConstsAsync: { [key: string]: SplitIO.Event } = asyncClient.Event; +splitEvent = asyncClient.Event.SDK_READY; +splitEvent = asyncClient.Event.SDK_READY_FROM_CACHE; +splitEvent = asyncClient.Event.SDK_READY_TIMED_OUT; +splitEvent = asyncClient.Event.SDK_UPDATE; // Client implements methods from NodeJS.Events. (same as for sync client, just for interface checking) -nodeAsyncClient = nodeAsyncClient.on(splitEvent, () => { }); -const a1: boolean = nodeAsyncClient.emit(splitEvent); -nodeAsyncClient = nodeAsyncClient.removeAllListeners(splitEvent); -nodeAsyncClient = nodeAsyncClient.removeAllListeners(); -const b1: number = nodeAsyncClient.listenerCount(splitEvent); -nodeEventEmitter = nodeAsyncClient; +asyncClient = asyncClient.on(splitEvent, () => { }); +const a1: boolean = asyncClient.emit(splitEvent); +asyncClient = asyncClient.removeAllListeners(splitEvent); +asyncClient = asyncClient.removeAllListeners(); +const b1: number = asyncClient.listenerCount(splitEvent); +nodeEventEmitter = asyncClient; // Ready, destroy and flush (same as for sync client, just for interface checking) -promise = nodeAsyncClient.ready(); -promise = nodeAsyncClient.destroy(); +promise = asyncClient.ready(); +promise = asyncClient.destroy(); promise = AsyncSDK.destroy(); // @TODO not public yet -// promise = nodeAsyncClient.flush(); +// promise = asyncClient.flush(); // We can call getTreatment but always with a key. -asyncTreatment = nodeAsyncClient.getTreatment(splitKey, 'mySplit'); +asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit'); // Attributes parameter is optional -asyncTreatment = nodeAsyncClient.getTreatment(splitKey, 'mySplit', attributes); +asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit', attributes); // We can call getTreatments but always with a key. -asyncTreatments = nodeAsyncClient.getTreatments(splitKey, ['mySplit']); +asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit']); // Attributes parameter is optional -asyncTreatments = nodeAsyncClient.getTreatments(splitKey, ['mySplit'], attributes); +asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit'], attributes); // We can call getTreatmentWithConfig but always with a key. -asyncTreatmentWithConfig = nodeAsyncClient.getTreatmentWithConfig(splitKey, 'mySplit'); +asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit'); // Attributes parameter is optional -asyncTreatmentWithConfig = nodeAsyncClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); +asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); // We can call getTreatments but always with a key. -asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfig(splitKey, ['mySplit']); +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit']); // Attributes parameter is optional -asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); // We can call getTreatmentsByFlagSet -asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSet(splitKey, 'set_a'); +asyncTreatments = asyncClient.getTreatmentsByFlagSet(splitKey, 'set_a'); // Attributes parameter is optional -asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); +asyncTreatments = asyncClient.getTreatmentsByFlagSet(splitKey, 'set_a', attributes); // We can call getTreatmentsByFlagSets -asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSets(splitKey, ['set_a']); +asyncTreatments = asyncClient.getTreatmentsByFlagSets(splitKey, ['set_a']); // Attributes parameter is optional -asyncTreatments = nodeAsyncClient.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); +asyncTreatments = asyncClient.getTreatmentsByFlagSets(splitKey, ['set_a'], attributes); // We can call getTreatmentsWithConfigByFlagSet -asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a'); // Attributes parameter is optional -asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSet(splitKey, 'set_a', attributes); // We can call getTreatmentsByFlagSets but always with a key. -asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a']); // Attributes parameter is optional -asyncTreatmentsWithConfig = nodeAsyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfigByFlagSets(splitKey, ['set_a'], attributes); // We can call track only with a key. -trackPromise = nodeAsyncClient.track(splitKey, 'myTrafficType', 'myEventType'); // all required params +trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType'); // all required params // Value parameter is optional. -trackPromise = nodeAsyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10); +trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10); // Properties parameter is optional -trackPromise = nodeAsyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); +trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); /**** Tests for IManager interface ****/ @@ -594,9 +594,23 @@ let fullAsyncSettings: SplitIO.INodeAsyncSettings = { labelsEnabled: false, IPAddressesEnabled: false }, + scheduler: { + featuresRefreshRate: 1, + impressionsRefreshRate: 1, + impressionsQueueSize: 1, + metricsRefreshRate: 1, + telemetryRefreshRate: 1, + segmentsRefreshRate: 1, + offlineRefreshRate: 1, + eventsPushRate: 1, + eventsQueueSize: 1 + }, startup: { readyTimeout: 1, + requestTimeoutBeforeReady: 1, + retriesOnFailureBeforeReady: 1 }, + features: mockedFeaturesPath, storage: { type: 'REDIS', options: { diff --git a/types/index.d.ts b/types/index.d.ts index 2bcd7c7db..e3f81c3e4 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -12,17 +12,17 @@ declare module JsSdk { * The settings parameter should be an object that complies with the SplitIO.INodeAsyncSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.INodeAsyncSDK; + export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.IAsyncSDK; /** * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.INodeSDK; + export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.ISDK; /** * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.IBrowserSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.ISDK; + export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.IBrowserSDK; } From 98df0fd7f6d9df03f38a19b059b82027e7cf175b Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 31 Oct 2024 00:59:00 -0300 Subject: [PATCH 18/20] Upgrade JS-commons --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES.txt | 1 - package-lock.json | 14 +++++++------- package.json | 2 +- types/client/index.d.ts | 2 +- types/server/index.d.ts | 4 ++-- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 6d498d43d..d28295fdb 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/refactor_type_definitions' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/refactor_type_definitions' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} strategy: matrix: environment: diff --git a/CHANGES.txt b/CHANGES.txt index d881aa7f5..c5a6cf638 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,7 +5,6 @@ - Renamed distribution folders from `/lib` to `/cjs` for CommonJS build, and `/es` to `/esm` for ECMAScript Modules build. - BREAKING CHANGES: - Dropped support for NodeJS v6. The SDK now requires NodeJS v14 or above. - - Renamed some TypeScript definitions in the SplitIO namespace to avoid conflicts with other libraries: `ISDK` to `INodeSDK`, `IAsyncSDK` to `INodeAsyncSDK`, `IBrowserSDK` to `ISDK`, `IClient` to `INodeClient`, `IAsyncClient` to `INodeAsyncClient`, `IBrowserClient` to `IClient`. - Removed internal ponyfills for the `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 provide a polyfill. - Removed the deprecated `GOOGLE_ANALYTICS_TO_SPLIT` and `SPLIT_TO_GOOGLE_ANALYTICS` integrations. The `integrations` configuration option has been removed from the SDK factory configuration, along with the associated interfaces in the TypeScript definitions. - Removed the `core.trafficType` configuration option (`SplitIO.IBrowserSettings['core']['trafficType]`) and the `trafficType` parameter from the SDK `client()` method in Browser (`SplitIO.IBrowserSDK['client']`). As a result, traffic types can no longer be bound to SDK clients, and the traffic type must be provided in the `track` method. diff --git a/package-lock.json b/package-lock.json index 5e7c259f2..446444bdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "11.0.0-rc.4", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.5", + "@splitsoftware/splitio-commons": "2.0.0-rc.6", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -869,9 +869,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.5.tgz", - "integrity": "sha512-hNLA3cfVj5yGSHpOyTQVzcU2kIceJtJOdatcuue2ENOesjwDHfpvEy/YkIgLcLwXpvUxTFKpZd1BRej8gSbWoA==", + "version": "2.0.0-rc.6", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.6.tgz", + "integrity": "sha512-A4Dk02ShJBjXqtPro6ylBAPc344Unnyk7YmEmvQqv1x4VUKloLw76PI7FgUgG7bM2UH079jSIeUg8HePW2PL1g==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -8587,9 +8587,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.5.tgz", - "integrity": "sha512-hNLA3cfVj5yGSHpOyTQVzcU2kIceJtJOdatcuue2ENOesjwDHfpvEy/YkIgLcLwXpvUxTFKpZd1BRej8gSbWoA==", + "version": "2.0.0-rc.6", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.6.tgz", + "integrity": "sha512-A4Dk02ShJBjXqtPro6ylBAPc344Unnyk7YmEmvQqv1x4VUKloLw76PI7FgUgG7bM2UH079jSIeUg8HePW2PL1g==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 3a73c4a9f..de1ed2243 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.5", + "@splitsoftware/splitio-commons": "2.0.0-rc.6", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/types/client/index.d.ts b/types/client/index.d.ts index 45efaa984..efa3a8f03 100644 --- a/types/client/index.d.ts +++ b/types/client/index.d.ts @@ -11,5 +11,5 @@ declare module JsSdk { * The settings parameter should be an object that complies with the SplitIO.IBrowserSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.ISDK; + export function SplitFactory(settings: SplitIO.IBrowserSettings): SplitIO.IBrowserSDK; } diff --git a/types/server/index.d.ts b/types/server/index.d.ts index f0e305fce..fcbc2bd59 100644 --- a/types/server/index.d.ts +++ b/types/server/index.d.ts @@ -11,11 +11,11 @@ declare module JsSdk { * The settings parameter should be an object that complies with the SplitIO.INodeAsyncSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.INodeAsyncSDK; + export function SplitFactory(settings: SplitIO.INodeAsyncSettings): SplitIO.IAsyncSDK; /** * Split.io SDK factory function. * The settings parameter should be an object that complies with the SplitIO.INodeSettings. * For more information read the corresponding article: @see {@link https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#configuration} */ - export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.INodeSDK; + export function SplitFactory(settings: SplitIO.INodeSettings): SplitIO.ISDK; } From 94670959378cc005515b6ad56e79ce6eb74290b3 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 31 Oct 2024 11:02:07 -0300 Subject: [PATCH 19/20] Update ts test --- ts-tests/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 562b95b91..2e2588d9f 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -12,6 +12,8 @@ */ import { SplitFactory } from '../types/index'; +import { SplitFactory as SplitFactoryCS } from '../types/client'; +import { SplitFactory as SplitFactorySS } from '../types/server'; let stringPromise: Promise; let splitNamesPromise: Promise; @@ -166,6 +168,9 @@ browserSettings = { SDK = SplitFactory(nodeSettings); AsyncSDK = SplitFactory(asyncSettings); BrowserSDK = SplitFactory(browserSettings); +SDK = SplitFactorySS(nodeSettings); +AsyncSDK = SplitFactorySS(asyncSettings); +BrowserSDK = SplitFactoryCS(browserSettings); // The settings values the SDK expose. const instantiatedSettingsCore: { From 4c9b7afcc80f1977197c9ea9534e039afee89232 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 31 Oct 2024 14:07:54 -0300 Subject: [PATCH 20/20] rc --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES.txt | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/settings/defaults/version.js | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d28295fdb..6d498d43d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/refactor_type_definitions' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/refactor_type_definitions' }} strategy: matrix: environment: diff --git a/CHANGES.txt b/CHANGES.txt index c5a6cf638..ab03511a1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -11.0.0 (October XX, 2024) +11.0.0 (November 1, 2024) - Added support for targeting rules based on large segments for browsers. - Added `factory.destroy()` method, which invokes the `destroy` method of all clients created by the factory. - Updated @splitsoftware/splitio-commons package to version 2.0.0 that includes major updates and updated some transitive dependencies for vulnerability fixes. diff --git a/package-lock.json b/package-lock.json index 446444bdf..7c93bfadf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.4", + "version": "11.0.0-rc.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.4", + "version": "11.0.0-rc.5", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.0.0-rc.6", diff --git a/package.json b/package.json index de1ed2243..952d43865 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.4", + "version": "11.0.0-rc.5", "description": "Split SDK", "files": [ "README.md", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 36355d51c..b48d27e57 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.0.0-rc.4'; +export const packageVersion = '11.0.0-rc.5';