diff --git a/CHANGES.txt b/CHANGES.txt index db1fa81e..29391a11 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +2.2.0 (March 28, 2025) + - Added new optional argument to the client `getTreatment` methods to allow passing additional evaluation options, such as a map of properties to append to the generated impression object sent to Split backend. + 2.1.0 (January 17, 2025) - Added support for the new impressions tracking toggle available on feature flags, both respecting the setting and including the new field being returned on `SplitView` type objects. Read more in our docs. diff --git a/package-lock.json b/package-lock.json index f15fce99..4cccfff2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio-commons", - "version": "2.1.0", + "version": "2.1.1-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-commons", - "version": "2.1.0", + "version": "2.1.1-rc.1", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -67,13 +67,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -266,18 +267,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -293,38 +294,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", - "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "node_modules/@babel/parser": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/types": "^7.26.10" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -495,9 +484,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -507,14 +496,14 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" @@ -542,14 +531,13 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1979,18 +1967,6 @@ "node": ">=8" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2379,20 +2355,6 @@ } ] }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -2459,21 +2421,6 @@ "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2812,15 +2759,6 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/escodegen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", @@ -3978,15 +3916,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", @@ -7465,18 +7394,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/supports-hyperlinks": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", @@ -7577,15 +7494,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8164,13 +8072,14 @@ } }, "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { @@ -8319,15 +8228,15 @@ } }, "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true }, "@babel/helper-validator-option": { @@ -8337,33 +8246,24 @@ "dev": true }, "@babel/helpers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", - "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" } }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "@babel/parser": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/types": "^7.26.10" } }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true - }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -8482,23 +8382,23 @@ } }, "@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", "dev": true, "requires": { "regenerator-runtime": "^0.14.0" } }, "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" } }, "@babel/traverse": { @@ -8520,14 +8420,13 @@ } }, "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" } }, "@bcoe/v8-coverage": { @@ -9608,15 +9507,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -9898,17 +9788,6 @@ "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "dev": true }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -9956,21 +9835,6 @@ "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -10228,12 +10092,6 @@ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, "escodegen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", @@ -11089,12 +10947,6 @@ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", "dev": true }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", @@ -13670,15 +13522,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, "supports-hyperlinks": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", @@ -13757,12 +13600,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/package.json b/package.json index d51bc14f..5f6a44d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "2.1.0", + "version": "2.1.1-rc.1", "description": "Split JavaScript SDK common components", "main": "cjs/index.js", "module": "esm/index.js", diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index 2c0b0c63..123f8eee 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -21,7 +21,7 @@ export const codesError: [number, string][] = [ // input validation [c.ERROR_EVENT_TYPE_FORMAT, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], [c.ERROR_NOT_PLAIN_OBJECT, '%s: %s must be a plain object.'], - [c.ERROR_SIZE_EXCEEDED, '%s: the maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], + [c.ERROR_SIZE_EXCEEDED, '%s: the maximum size allowed for the properties is 32768 bytes, which was exceeded.'], [c.ERROR_NOT_FINITE, '%s: value must be a finite number.'], [c.ERROR_NULL, '%s: you passed a null or undefined %s. It must be a non-empty string.'], [c.ERROR_TOO_LONG, '%s: %s too long. It must have 250 characters or less.'], diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index 52487f95..568771a8 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -18,7 +18,7 @@ export const codesWarn: [number, string][] = codesError.concat([ [c.CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], // input validation [c.WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'], - [c.WARN_TRIMMING_PROPERTIES, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], + [c.WARN_TRIMMING_PROPERTIES, '%s: more than 300 properties were provided. Some of them will be trimmed when processed.'], [c.WARN_CONVERTING, '%s: %s "%s" is not of type string, converting.'], [c.WARN_TRIMMING, '%s: %s "%s" has extra whitespace, trimming.'], [c.WARN_NOT_EXISTENT_SPLIT, '%s: feature flag "%s" does not exist in this environment. Please double check what feature flags exist in the Split user interface.'], diff --git a/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts b/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts index e007dc54..65aa8ef1 100644 --- a/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts +++ b/src/sdkClient/__tests__/clientAttributesDecoration.spec.ts @@ -33,7 +33,7 @@ const clientMock = { } }; // @ts-expect-error -const client = clientAttributesDecoration(loggerMock, clientMock); +const client: any = clientAttributesDecoration(loggerMock, clientMock); test('ATTRIBUTES DECORATION / storage', () => { @@ -91,9 +91,7 @@ describe('ATTRIBUTES DECORATION / validation', () => { test('Should return false if it is an invalid attributes map', () => { expect(client.setAttribute('', 'attributeValue')).toEqual(false); // It should be invalid if the attribute key is not a string - // @ts-expect-error expect(client.setAttribute('attributeKey1', new Date())).toEqual(false); // It should be invalid if the attribute value is not a String, Number, Boolean or Lists. - // @ts-expect-error expect(client.setAttribute('attributeKey2', { 'some': 'object' })).toEqual(false); // It should be invalid if the attribute value is not a String, Number, Boolean or Lists. expect(client.setAttribute('attributeKey3', Infinity)).toEqual(false); // It should be invalid if the attribute value is not a String, Number, Boolean or Lists. @@ -153,180 +151,31 @@ describe('ATTRIBUTES DECORATION / validation', () => { describe('ATTRIBUTES DECORATION / evaluation', () => { - test('Evaluation attributes logic and precedence / getTreatment', () => { - + test.each([ + ['getTreatment', 'split'], + ['getTreatments', ['split']], + ['getTreatmentWithConfig', 'split'], + ['getTreatmentsWithConfig', ['split']], + ['getTreatmentsByFlagSet', 'set'], + ['getTreatmentsWithConfigByFlagSet', 'set'], + ['getTreatmentsByFlagSets', ['set']], + ['getTreatmentsWithConfigByFlagSets', ['set']] + ])('Evaluation attributes logic and precedence / %s', (method, param) => { // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatment('key', 'split')).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatment('key', 'split', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api + expect(client[method]('key', param)).toEqual(undefined); // Nothing changes if no attributes were provided using the new api + expect(client[method]('key', param, { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty client.setAttribute('func_attr_bool', false); expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatment('key', 'split', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatment('key', 'split', null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatment('key', 'split', { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations + expect(client[method]('key', param, { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones + expect(client[method]('key', param, null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations + expect(client[method]('key', param, { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations client.setAttributes({ func_attr_str: 'false' }); expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatment('key', 'split', { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatment('key', 'split', null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatment('key', 'split')).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. + expect(client[method]('key', param, { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones + expect(client[method]('key', param, null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. + expect(client[method]('key', param)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. expect(client.clearAttributes()).toEqual(true); - - }); - - test('Evaluation attributes logic and precedence / getTreatments', () => { - - // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatments('key', ['split'])).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatments('key', ['split'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api - expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty - client.setAttribute('func_attr_bool', false); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatments('key', ['split'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatments('key', ['split'], null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatments('key', ['split'], { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations - client.setAttributes({ func_attr_str: 'false' }); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatments('key', ['split'], { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatments('key', ['split'], null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatments('key', ['split'])).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.clearAttributes()).toEqual(true); - - }); - - test('Evaluation attributes logic and precedence / getTreatmentWithConfig', () => { - - // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatmentWithConfig('key', 'split')).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatmentWithConfig('key', 'split', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api - expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty - client.setAttribute('func_attr_bool', false); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatmentWithConfig('key', 'split', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentWithConfig('key', 'split', null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatmentWithConfig('key', 'split', { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations - client.setAttributes({ func_attr_str: 'false' }); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatmentWithConfig('key', 'split', { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentWithConfig('key', 'split', null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatmentWithConfig('key', 'split')).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.clearAttributes()).toEqual(true); - - }); - - test('Evaluation attributes logic and precedence / getTreatmentsWithConfig', () => { - - // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatmentsWithConfig('key', ['split'])).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatmentsWithConfig('key', ['split'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api - expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty - client.setAttribute('func_attr_bool', false); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatmentsWithConfig('key', ['split'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsWithConfig('key', ['split'], null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatmentsWithConfig('key', ['split'], { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations - client.setAttributes({ func_attr_str: 'false' }); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatmentsWithConfig('key', ['split'], { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsWithConfig('key', ['split'], null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatmentsWithConfig('key', ['split'])).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - client.clearAttributes(); - - }); - - test('Evaluation attributes logic and precedence / getTreatmentsByFlagSets', () => { - - // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatmentsByFlagSets('key', ['set'])).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatmentsByFlagSets('key', ['set'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api - expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty - client.setAttribute('func_attr_bool', false); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatmentsByFlagSets('key', ['set'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsByFlagSets('key', ['set'], null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatmentsByFlagSets('key', ['set'], { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations - client.setAttributes({ func_attr_str: 'false' }); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatmentsByFlagSets('key', ['set'], { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsByFlagSets('key', ['set'], null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatmentsByFlagSets('key', ['set'])).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - client.clearAttributes(); - - }); - - test('Evaluation attributes logic and precedence / getTreatmentsWithConfigByFlagSets', () => { - - // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'])).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api - expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty - client.setAttribute('func_attr_bool', false); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'], { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'], null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'], { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations - client.setAttributes({ func_attr_str: 'false' }); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'], { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'], null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatmentsWithConfigByFlagSets('key', ['set'])).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - client.clearAttributes(); - - }); - - test('Evaluation attributes logic and precedence / getTreatmentsByFlagSet', () => { - - // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatmentsByFlagSet('key', 'set')).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatmentsByFlagSet('key', 'set', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api - expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty - client.setAttribute('func_attr_bool', false); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatmentsByFlagSet('key', 'set', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsByFlagSet('key', 'set', null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatmentsByFlagSet('key', 'set', { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations - client.setAttributes({ func_attr_str: 'false' }); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatmentsByFlagSet('key', 'set', { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsByFlagSet('key', 'set', null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatmentsByFlagSet('key', 'set')).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - client.clearAttributes(); - - }); - - test('Evaluation attributes logic and precedence / getTreatmentsWithConfigByFlagSet', () => { - - // If the same attribute is “cached” and provided on the function, the value received on the function call takes precedence. - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set')).toEqual(undefined); // Nothing changes if no attributes were provided using the new api - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Nothing changes if no attributes were provided using the new api - expect(client.getAttributes()).toEqual({}); // Attributes in memory storage must be empty - client.setAttribute('func_attr_bool', false); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false }); // In memory attribute storage must have the unique stored attribute - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set', { func_attr_bool: true, func_attr_str: 'true' })).toEqual({ func_attr_bool: true, func_attr_str: 'true' }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set', null)).toEqual({ func_attr_bool: false }); // API attributes should be kept in memory and use for evaluations - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set', { func_attr_str: 'true' })).toEqual({ func_attr_bool: false, func_attr_str: 'true' }); // API attributes should be kept in memory and use for evaluations - client.setAttributes({ func_attr_str: 'false' }); - expect(client.getAttributes()).toEqual({ 'func_attr_bool': false, 'func_attr_str': 'false' }); // In memory attribute storage must have two stored attributes - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set', { func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 })).toEqual({ func_attr_bool: true, func_attr_str: 'true', func_attr_number: 1 }); // Function attributes has precedence against api ones - // @ts-ignore - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set', null)).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - expect(client.getTreatmentsWithConfigByFlagSet('key', 'set')).toEqual({ func_attr_bool: false, func_attr_str: 'false' }); // If the getTreatment function is called without attributes, stored attributes will be used to evaluate. - client.clearAttributes(); - }); }); diff --git a/src/sdkClient/__tests__/clientInputValidation.spec.ts b/src/sdkClient/__tests__/clientInputValidation.spec.ts index 0664c179..f70845f7 100644 --- a/src/sdkClient/__tests__/clientInputValidation.spec.ts +++ b/src/sdkClient/__tests__/clientInputValidation.spec.ts @@ -3,13 +3,15 @@ import { clientInputValidationDecorator } from '../clientInputValidation'; // Mocks import { DebugLogger } from '../../logger/browser/DebugLogger'; +import { createClientMock } from './testUtils'; const settings: any = { log: DebugLogger(), sync: { __splitFiltersValidation: { groupedFilters: { bySet: [] } } } }; -const client: any = {}; +const EVALUATION_RESULT = 'on'; +const client: any = createClientMock(EVALUATION_RESULT); const readinessManager: any = { isReady: () => true, @@ -52,4 +54,54 @@ describe('clientInputValidationDecorator', () => { // @TODO should be 8, but there is an additional log from `getTreatmentsByFlagSet` and `getTreatmentsWithConfigByFlagSet` that should be removed expect(logSpy).toBeCalledTimes(10); }); + + test('should evaluate but log an error if the passed 4th argument (evaluation options) is invalid', () => { + expect(clientWithValidation.getTreatment('key', 'ff', undefined, 'invalid')).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[ERROR] splitio => getTreatment: evaluation options must be a plain object.'); + expect(client.getTreatment).toBeCalledWith('key', 'ff', undefined, undefined); + + expect(clientWithValidation.getTreatmentWithConfig('key', 'ff', undefined, { properties: 'invalid' })).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[ERROR] splitio => getTreatmentWithConfig: properties must be a plain object.'); + expect(client.getTreatmentWithConfig).toBeCalledWith('key', 'ff', undefined, undefined); + + expect(clientWithValidation.getTreatments('key', ['ff'], undefined, { properties: 'invalid' })).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[ERROR] splitio => getTreatments: properties must be a plain object.'); + expect(client.getTreatments).toBeCalledWith('key', ['ff'], undefined, undefined); + + expect(clientWithValidation.getTreatmentsWithConfig('key', ['ff'], {}, { properties: true })).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[ERROR] splitio => getTreatmentsWithConfig: properties must be a plain object.'); + expect(client.getTreatmentsWithConfig).toBeCalledWith('key', ['ff'], {}, undefined); + + expect(clientWithValidation.getTreatmentsByFlagSet('key', 'flagSet', undefined, { properties: 'invalid' })).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[ERROR] splitio => getTreatmentsByFlagSet: properties must be a plain object.'); + expect(client.getTreatmentsByFlagSet).toBeCalledWith('key', 'flagset', undefined, undefined); + + expect(clientWithValidation.getTreatmentsWithConfigByFlagSet('key', 'flagSet', {}, { properties: 'invalid' })).toBe(EVALUATION_RESULT); + expect(logSpy).toBeCalledWith('[ERROR] splitio => getTreatmentsWithConfigByFlagSet: properties must be a plain object.'); + expect(client.getTreatmentsWithConfigByFlagSet).toBeCalledWith('key', 'flagset', {}, undefined); + + expect(clientWithValidation.getTreatmentsByFlagSets('key', ['flagSet'], undefined, { properties: 'invalid' })).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[ERROR] splitio => getTreatmentsByFlagSets: properties must be a plain object.'); + expect(client.getTreatmentsByFlagSets).toBeCalledWith('key', ['flagset'], undefined, undefined); + + expect(clientWithValidation.getTreatmentsWithConfigByFlagSets('key', ['flagSet'], {}, { properties: 'invalid' })).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[ERROR] splitio => getTreatmentsWithConfigByFlagSets: properties must be a plain object.'); + expect(client.getTreatmentsWithConfigByFlagSets).toBeCalledWith('key', ['flagset'], {}, undefined); + }); + + test('should sanitize the properties in the 4th argument', () => { + expect(clientWithValidation.getTreatment('key', 'ff', undefined, { properties: { toSanitize: /asd/, correct: 100 }})).toBe(EVALUATION_RESULT); + expect(logSpy).toHaveBeenLastCalledWith('[WARN] splitio => getTreatment: Property "toSanitize" is of invalid type. Setting value to null.'); + expect(client.getTreatment).toBeCalledWith('key', 'ff', undefined, { properties: { toSanitize: null, correct: 100 }}); + }); + + test('should ignore the properties in the 4th argument if an empty object is passed', () => { + expect(clientWithValidation.getTreatment('key', 'ff', undefined, { properties: {} })).toBe(EVALUATION_RESULT); + expect(client.getTreatment).toHaveBeenLastCalledWith('key', 'ff', undefined, undefined); + + expect(clientWithValidation.getTreatment('key', 'ff', undefined, { properties: undefined })).toBe(EVALUATION_RESULT); + expect(client.getTreatment).toHaveBeenLastCalledWith('key', 'ff', undefined, undefined); + + expect(logSpy).not.toBeCalled(); + }); }); diff --git a/src/sdkClient/__tests__/testUtils.ts b/src/sdkClient/__tests__/testUtils.ts index 901897e3..dab0085a 100644 --- a/src/sdkClient/__tests__/testUtils.ts +++ b/src/sdkClient/__tests__/testUtils.ts @@ -8,3 +8,18 @@ export function assertClientApi(client: any, sdkStatus?: object) { expect(typeof client[method]).toBe('function'); }); } + +export function createClientMock(returnValue: any) { + + return { + getTreatment: jest.fn(()=> returnValue), + getTreatmentWithConfig: jest.fn(()=> returnValue), + getTreatments: jest.fn(()=> returnValue), + getTreatmentsWithConfig: jest.fn(()=> returnValue), + getTreatmentsByFlagSets: jest.fn(()=> returnValue), + getTreatmentsWithConfigByFlagSets: jest.fn(()=> returnValue), + getTreatmentsByFlagSet: jest.fn(()=> returnValue), + getTreatmentsWithConfigByFlagSet: jest.fn(()=> returnValue), + track: jest.fn(()=> returnValue), + }; +} diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index 1139a272..0e526f72 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -23,6 +23,14 @@ function treatmentsNotReady(featureFlagNames: string[]) { return evaluations; } +function stringify(options?: SplitIO.EvaluationOptions) { + if (options && options.properties) { + try { + return JSON.stringify(options.properties); + } catch { /* JSON.stringify should never throw with validated options, but handling just in case */ } + } +} + /** * Creator of base client with getTreatments and track methods. */ @@ -31,12 +39,12 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl const { log, mode } = settings; const isAsync = isConsumerMode(mode); - function getTreatment(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined, withConfig = false, methodName = GET_TREATMENT) { + function getTreatment(key: SplitIO.SplitKey, featureFlagName: string, attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions, withConfig = false, methodName = GET_TREATMENT) { const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENT_WITH_CONFIG : TREATMENT); const wrapUp = (evaluationResult: IEvaluationResult) => { const queue: ImpressionDecorated[] = []; - const treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, methodName, queue); + const treatment = processEvaluation(evaluationResult, featureFlagName, key, stringify(options), withConfig, methodName, queue); impressionsTracker.track(queue, attributes); stopTelemetryTracker(queue[0] && queue[0].imp.label); @@ -52,18 +60,19 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl return thenable(evaluation) ? evaluation.then((res) => wrapUp(res)) : wrapUp(evaluation); } - function getTreatmentWithConfig(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined) { - return getTreatment(key, featureFlagName, attributes, true, GET_TREATMENT_WITH_CONFIG); + function getTreatmentWithConfig(key: SplitIO.SplitKey, featureFlagName: string, attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions) { + return getTreatment(key, featureFlagName, attributes, options, true, GET_TREATMENT_WITH_CONFIG); } - function getTreatments(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false, methodName = GET_TREATMENTS) { + function getTreatments(key: SplitIO.SplitKey, featureFlagNames: string[], attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions, withConfig = false, methodName = GET_TREATMENTS) { const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENTS_WITH_CONFIG : TREATMENTS); const wrapUp = (evaluationResults: Record) => { const queue: ImpressionDecorated[] = []; - const treatments: Record = {}; + const treatments: SplitIO.Treatments | SplitIO.TreatmentsWithConfig = {}; + const properties = stringify(options); Object.keys(evaluationResults).forEach(featureFlagName => { - treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue); + treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, properties, withConfig, methodName, queue); }); impressionsTracker.track(queue, attributes); @@ -80,19 +89,19 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations); } - function getTreatmentsWithConfig(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined) { - return getTreatments(key, featureFlagNames, attributes, true, GET_TREATMENTS_WITH_CONFIG); + function getTreatmentsWithConfig(key: SplitIO.SplitKey, featureFlagNames: string[], attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions) { + return getTreatments(key, featureFlagNames, attributes, options, true, GET_TREATMENTS_WITH_CONFIG); } - function getTreatmentsByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false, method: Method = TREATMENTS_BY_FLAGSETS, methodName = GET_TREATMENTS_BY_FLAG_SETS) { + function getTreatmentsByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions, withConfig = false, method: Method = TREATMENTS_BY_FLAGSETS, methodName = GET_TREATMENTS_BY_FLAG_SETS) { const stopTelemetryTracker = telemetryTracker.trackEval(method); const wrapUp = (evaluationResults: Record) => { const queue: ImpressionDecorated[] = []; - const treatments: Record = {}; - const evaluations = evaluationResults; - Object.keys(evaluations).forEach(featureFlagName => { - treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue); + const treatments: SplitIO.Treatments | SplitIO.TreatmentsWithConfig = {}; + const properties = stringify(options); + Object.keys(evaluationResults).forEach(featureFlagName => { + treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, properties, withConfig, methodName, queue); }); impressionsTracker.track(queue, attributes); @@ -109,16 +118,16 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations); } - function getTreatmentsWithConfigByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes: SplitIO.Attributes | undefined) { - return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS); + function getTreatmentsWithConfigByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions) { + return getTreatmentsByFlagSets(key, flagSetNames, attributes, options, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS); } - function getTreatmentsByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes: SplitIO.Attributes | undefined) { - return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, TREATMENTS_BY_FLAGSET, GET_TREATMENTS_BY_FLAG_SET); + function getTreatmentsByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions) { + return getTreatmentsByFlagSets(key, [flagSetName], attributes, options, false, TREATMENTS_BY_FLAGSET, GET_TREATMENTS_BY_FLAG_SET); } - function getTreatmentsWithConfigByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes: SplitIO.Attributes | undefined) { - return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET); + function getTreatmentsWithConfigByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes?: SplitIO.Attributes, options?: SplitIO.EvaluationOptions) { + return getTreatmentsByFlagSets(key, [flagSetName], attributes, options, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET); } // Internal function @@ -126,7 +135,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl evaluation: IEvaluationResult, featureFlagName: string, key: SplitIO.SplitKey, - attributes: SplitIO.Attributes | undefined, + properties: string | undefined, withConfig: boolean, invokingMethodName: string, queue: ImpressionDecorated[] @@ -148,6 +157,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl bucketingKey, label, changeNumber: changeNumber as number, + properties }, disabled: impressionsDisabled }); diff --git a/src/sdkClient/clientAttributesDecoration.ts b/src/sdkClient/clientAttributesDecoration.ts index cf31b5d3..b9a901db 100644 --- a/src/sdkClient/clientAttributesDecoration.ts +++ b/src/sdkClient/clientAttributesDecoration.ts @@ -20,50 +20,44 @@ export function clientAttributesDecoration 0) { - return objectAssign({}, storedAttributes, maybeAttributes); - } - return maybeAttributes; + return Object.keys(storedAttributes).length > 0 ? + objectAssign({}, storedAttributes, maybeAttributes) : + maybeAttributes; } return objectAssign(client, { @@ -75,7 +69,6 @@ export function clientAttributesDecoration -1 ? @@ -43,6 +44,7 @@ export function clientInputValidationDecorator res[split] = CONTROL); @@ -93,11 +96,11 @@ export function clientInputValidationDecorator res[split] = objectAssign({}, CONTROL_WITH_CONFIG)); @@ -106,41 +109,41 @@ export function clientInputValidationDecorator 0 ? { properties } : undefined; + } else if (maybeOptions) { + log.error(ERROR_NOT_PLAIN_OBJECT, [method, 'evaluation options']); + } + return undefined; +} diff --git a/src/utils/inputValidation/index.ts b/src/utils/inputValidation/index.ts index 93b09ab7..96cf4be6 100644 --- a/src/utils/inputValidation/index.ts +++ b/src/utils/inputValidation/index.ts @@ -11,3 +11,4 @@ export { validateIfNotDestroyed, validateIfOperational } from './isOperational'; export { validateSplitExistence } from './splitExistence'; export { validateTrafficTypeExistence } from './trafficTypeExistence'; export { validatePreloadedData } from './preloadedData'; +export { validateEvaluationOptions } from './eventProperties'; diff --git a/types/splitio.d.ts b/types/splitio.d.ts index 0cab4b66..4102a7fc 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -778,6 +778,15 @@ declare namespace SplitIO { type Properties = { [propertyName: string]: string | number | boolean | null; }; + /** + * Evaluation options object for getTreatment methods. + */ + type EvaluationOptions = { + /** + * Optional properties to append to the generated impression object sent to Split backend. + */ + properties?: Properties; + } /** * The SplitKey object format. */ @@ -803,14 +812,42 @@ declare namespace SplitIO { * Impression DTO generated by the SDK when processing evaluations. */ type ImpressionDTO = { + /** + * Feature flag name. + */ feature: string; + /** + * Key. + */ keyName: string; + /** + * Treatment value. + */ treatment: string; + /** + * Impression timestamp. + */ time: number; + /** + * Bucketing Key + */ bucketingKey?: string; + /** + * Rule label + */ label: string; + /** + * Version of the feature flag + */ changeNumber: number; + /** + * Previous time + */ pt?: number; + /** + * JSON stringified version of the impression properties. + */ + properties?: string; } /** * Object with information about an impression. It contains the generated impression DTO as well as @@ -1514,73 +1551,80 @@ declare namespace SplitIO { * @param key - The string key representing the consumer. * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The treatment string. */ - getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes): Treatment; + getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): Treatment; /** * Returns a TreatmentWithConfig value, which is an object with both treatment and config string for the given feature. * * @param key - The string key representing the consumer. * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. - * @returns The TreatmentWithConfig, the object containing the treatment string and the - * configuration stringified JSON (or null if there was no config for that treatment). + * @param options - An object of type EvaluationOptions for advanced evaluation options. + * @returns The TreatmentWithConfig object that contains 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; + getTreatmentWithConfig(key: SplitKey, featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): TreatmentWithConfig; /** * Returns a Treatments value, which is an object map with the treatments for the given features. * * @param key - The string key representing the consumer. * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The treatments object map. */ - getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): Treatments; + getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the TreatmentWithConfig objects */ - getTreatmentsWithConfig(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): TreatmentsWithConfig; + getTreatmentsWithConfig(key: SplitKey, featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): TreatmentsWithConfig; /** * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. * * @param key - The string key representing the consumer. * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the Treatment objects */ - getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): Treatments; + getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the TreatmentWithConfig objects */ - getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): TreatmentsWithConfig; + getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the Treatment objects */ - getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): Treatments; + getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the TreatmentWithConfig objects */ - getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): TreatmentsWithConfig; + getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): TreatmentsWithConfig; /** * Tracks an event to be fed to the results product on Split user interface. * @@ -1605,72 +1649,80 @@ declare namespace SplitIO { * @param key - The string key representing the consumer. * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatment promise that resolves to the treatment string. */ - getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes): AsyncTreatment; + getTreatment(key: SplitKey, featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): AsyncTreatment; /** * Returns a TreatmentWithConfig value, which will be (or eventually be) an object with both treatment and config string for the given feature. * * @param key - The string key representing the consumer. * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentWithConfig promise that resolves to the TreatmentWithConfig object. */ - getTreatmentWithConfig(key: SplitKey, featureFlagName: string, attributes?: Attributes): AsyncTreatmentWithConfig; + getTreatmentWithConfig(key: SplitKey, featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): AsyncTreatmentWithConfig; /** * Returns a Treatments value, which will be (or eventually be) an object map with the treatments for the given features. * * @param key - The string key representing the consumer. * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatments promise that resolves to the treatments object map. */ - getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): AsyncTreatments; + getTreatments(key: SplitKey, featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentsWithConfig promise that resolves to the map of TreatmentsWithConfig objects. */ - getTreatmentsWithConfig(key: SplitKey, featureFlagNames: string[], attributes?: Attributes): AsyncTreatmentsWithConfig; + getTreatmentsWithConfig(key: SplitKey, featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): AsyncTreatmentsWithConfig; /** * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. * * @param key - The string key representing the consumer. * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatments promise that resolves to the treatments object map. */ - getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): AsyncTreatments; + getTreatmentsByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentsWithConfig promise that resolves to the map of TreatmentsWithConfig objects. */ - getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes): AsyncTreatmentsWithConfig; + getTreatmentsWithConfigByFlagSet(key: SplitKey, flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatments promise that resolves to the treatments object map. */ - getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): AsyncTreatments; + getTreatmentsByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param key - The string key representing the consumer. * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentsWithConfig promise that resolves to the map of TreatmentsWithConfig objects. */ - getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes): AsyncTreatmentsWithConfig; + getTreatmentsWithConfigByFlagSets(key: SplitKey, flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): 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). * @@ -1735,65 +1787,73 @@ declare namespace SplitIO { * * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The treatment string. */ - getTreatment(featureFlagName: string, attributes?: Attributes): Treatment; + getTreatment(featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): Treatment; /** * Returns a TreatmentWithConfig value, which is an object with both treatment and config string for the given feature. * * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. - * @returns The map containing the treatment and the configuration stringified JSON (or null if there was no config for that treatment). + * @param options - An object of type EvaluationOptions for advanced evaluation options. + * @returns The TreatmentWithConfig object that contains the treatment string and the configuration stringified JSON (or null if there was no config for that treatment). */ - getTreatmentWithConfig(featureFlagName: string, attributes?: Attributes): TreatmentWithConfig; + getTreatmentWithConfig(featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): TreatmentWithConfig; /** * Returns a Treatments value, which is an object map with the treatments for the given features. * * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The treatments object map. */ - getTreatments(featureFlagNames: string[], attributes?: Attributes): Treatments; + getTreatments(featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the TreatmentWithConfig objects */ - getTreatmentsWithConfig(featureFlagNames: string[], attributes?: Attributes): TreatmentsWithConfig; + getTreatmentsWithConfig(featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): TreatmentsWithConfig; /** * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. * * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the Treatments objects */ - getTreatmentsByFlagSet(flagSet: string, attributes?: Attributes): Treatments; + getTreatmentsByFlagSet(flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the TreatmentWithConfig objects */ - getTreatmentsWithConfigByFlagSet(flagSet: string, attributes?: Attributes): TreatmentsWithConfig; + getTreatmentsWithConfigByFlagSet(flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the Treatments objects */ - getTreatmentsByFlagSets(flagSets: string[], attributes?: Attributes): Treatments; + getTreatmentsByFlagSets(flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns The map with all the TreatmentWithConfig objects */ - getTreatmentsWithConfigByFlagSets(flagSets: string[], attributes?: Attributes): TreatmentsWithConfig; + getTreatmentsWithConfigByFlagSets(flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): TreatmentsWithConfig; /** * Tracks an event to be fed to the results product on Split user interface. * @@ -1814,65 +1874,73 @@ declare namespace SplitIO { * * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatment promise that resolves to the treatment string. */ - getTreatment(featureFlagName: string, attributes?: Attributes): AsyncTreatment; + getTreatment(featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): AsyncTreatment; /** * Returns a TreatmentWithConfig value, which will be (or eventually be) an object with both treatment and config string for the given feature. * * @param featureFlagName - The string that represents the feature flag we want to get the treatment. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentWithConfig promise that resolves to the TreatmentWithConfig object. */ - getTreatmentWithConfig(featureFlagName: string, attributes?: Attributes): AsyncTreatmentWithConfig; + getTreatmentWithConfig(featureFlagName: string, attributes?: Attributes, options?: EvaluationOptions): AsyncTreatmentWithConfig; /** * Returns a Treatments value, which will be (or eventually be) an object map with the treatments for the given features. * * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatments promise that resolves to the treatments object map. */ - getTreatments(featureFlagNames: string[], attributes?: Attributes): AsyncTreatments; + getTreatments(featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param featureFlagNames - An array of the feature flag names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentsWithConfig promise that resolves to the TreatmentsWithConfig object. */ - getTreatmentsWithConfig(featureFlagNames: string[], attributes?: Attributes): AsyncTreatmentsWithConfig; + getTreatmentsWithConfig(featureFlagNames: string[], attributes?: Attributes, options?: EvaluationOptions): AsyncTreatmentsWithConfig; /** * Returns a Treatments value, which is an object map with the treatments for the feature flags related to the given flag set. * * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatments promise that resolves to the treatments object map. */ - getTreatmentsByFlagSet(flagSet: string, attributes?: Attributes): AsyncTreatments; + getTreatmentsByFlagSet(flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param flagSet - The flag set name we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentsWithConfig promise that resolves to the TreatmentsWithConfig object. */ - getTreatmentsWithConfigByFlagSet(flagSet: string, attributes?: Attributes): AsyncTreatmentsWithConfig; + getTreatmentsWithConfigByFlagSet(flagSet: string, attributes?: Attributes, options?: EvaluationOptions): 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. * * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns Treatments promise that resolves to the treatments object map. */ - getTreatmentsByFlagSets(flagSets: string[], attributes?: Attributes): AsyncTreatments; + getTreatmentsByFlagSets(flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): 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. * * @param flagSets - An array of the flag set names we want to get the treatments. * @param attributes - An object of type Attributes defining the attributes for the given key. + * @param options - An object of type EvaluationOptions for advanced evaluation options. * @returns TreatmentsWithConfig promise that resolves to the TreatmentsWithConfig object. */ - getTreatmentsWithConfigByFlagSets(flagSets: string[], attributes?: Attributes): AsyncTreatmentsWithConfig; + getTreatmentsWithConfigByFlagSets(flagSets: string[], attributes?: Attributes, options?: EvaluationOptions): 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). *