From 8fd3ea7396b7552c43d79e6e21dbb69329372b3c Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:42:45 +0800 Subject: [PATCH 1/9] Fix readme title (#95) * fix readme bug * fix bug --- src/feature-management-applicationinsights-node/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/feature-management-applicationinsights-node/README.md b/src/feature-management-applicationinsights-node/README.md index 695a421..ef4d9cb 100644 --- a/src/feature-management-applicationinsights-node/README.md +++ b/src/feature-management-applicationinsights-node/README.md @@ -1,6 +1,6 @@ -# Microsoft Feature Management Application Insights Plugin for Browser +# Microsoft Feature Management Application Insights Plugin for Node -Feature Management Application Insights Plugin for Browser provides a solution for sending feature flag evaluation events produced by the Feature Management library. +Feature Management Application Insights Plugin for Node provides a solution for sending feature flag evaluation events produced by the Feature Management library. ## Getting Started From 771c2b98548adc1e442d854fe7e0990c9266a668 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:19:15 +0800 Subject: [PATCH 2/9] Use commonjs for node example in README (#96) * use commonjs for node example * fix typo * update --- .../README.md | 2 +- .../README.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/feature-management-applicationinsights-browser/README.md b/src/feature-management-applicationinsights-browser/README.md index 61622d7..bf04bf0 100644 --- a/src/feature-management-applicationinsights-browser/README.md +++ b/src/feature-management-applicationinsights-browser/README.md @@ -12,7 +12,7 @@ import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "@microso import { createTelemetryPublisher, trackEvent } from "@microsoft/feature-management-applicationinsights-browser"; const appInsights = new ApplicationInsights({ config: { - connectionString: CONNECTION_STRING + connectionString: "" }}); appInsights.loadAppInsights(); diff --git a/src/feature-management-applicationinsights-node/README.md b/src/feature-management-applicationinsights-node/README.md index ef4d9cb..bdef2f6 100644 --- a/src/feature-management-applicationinsights-node/README.md +++ b/src/feature-management-applicationinsights-node/README.md @@ -7,26 +7,26 @@ Feature Management Application Insights Plugin for Node provides a solution for ### Prerequisites - Node.js LTS version +- `applicationinsights` SDK v2(classic) ### Usage ``` javascript -import appInsights from "applicationinsights"; -import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "@microsoft/feature-management"; -import { createTelemetryPublisher, trackEvent } from "@microsoft/feature-management-applicationinsights-node"; +const appInsights = require("applicationinsights"); +appInsights.setup(process.env.APPINSIGHTS_CONNECTION_STRING).start(); -appInsights.setup(CONNECTION_STRING) - .start(); +const { FeatureManager, ConfigurationObjectFeatureFlagProvider } = require("@microsoft/feature-management"); +const { createTelemetryPublisher, trackEvent } = require("@microsoft/feature-management-applicationinsights-node"); const publishTelemetry = createTelemetryPublisher(appInsights.defaultClient); const provider = new ConfigurationObjectFeatureFlagProvider(jsonObject); const featureManager = new FeatureManager(provider, {onFeatureEvaluated: publishTelemetry}); // FeatureEvaluation event will be emitted when a feature flag is evaluated -featureManager.getVariant("TestFeature", {userId : TARGETING_ID}).then((variant) => { /* do something*/ }); +featureManager.getVariant("TestFeature", {userId : ""}).then((variant) => { /* do something*/ }); // Emit a custom event with targeting id attached. -trackEvent(appInsights.defaultClient, TARGETING_ID, {name: "TestEvent"}); +trackEvent(appInsights.defaultClient, "", {name: "TestEvent"}); ``` ## Contributing From a5710ac2de1290b8190f63314ad788c3699f0cc0 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Mon, 10 Feb 2025 10:57:29 +0800 Subject: [PATCH 3/9] update node example (#97) --- src/feature-management-applicationinsights-node/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feature-management-applicationinsights-node/README.md b/src/feature-management-applicationinsights-node/README.md index bdef2f6..b08f98a 100644 --- a/src/feature-management-applicationinsights-node/README.md +++ b/src/feature-management-applicationinsights-node/README.md @@ -26,7 +26,7 @@ const featureManager = new FeatureManager(provider, {onFeatureEvaluated: publish featureManager.getVariant("TestFeature", {userId : ""}).then((variant) => { /* do something*/ }); // Emit a custom event with targeting id attached. -trackEvent(appInsights.defaultClient, "", {name: "TestEvent"}); +trackEvent(appInsights.defaultClient, "", {name: "TestEvent", properties: {"Tag": "Some Value"}}); ``` ## Contributing From 1f8c1b21a85151af9f4d4206d82136097ef680b4 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Wed, 12 Feb 2025 13:47:35 +0800 Subject: [PATCH 4/9] version bump 2.0.1 (#99) --- .../package.json | 4 ++-- .../src/version.ts | 2 +- src/feature-management-applicationinsights-node/package.json | 4 ++-- .../src/version.ts | 2 +- src/feature-management/package-lock.json | 4 ++-- src/feature-management/package.json | 2 +- src/feature-management/src/version.ts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/feature-management-applicationinsights-browser/package.json b/src/feature-management-applicationinsights-browser/package.json index 64ba877..33d3f08 100644 --- a/src/feature-management-applicationinsights-browser/package.json +++ b/src/feature-management-applicationinsights-browser/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/feature-management-applicationinsights-browser", - "version": "2.0.0", + "version": "2.0.1", "description": "Feature Management Application Insights Plugin for Browser provides a solution for sending feature flag evaluation events produced by the Feature Management library.", "main": "./dist/esm/index.js", "module": "./dist/esm/index.js", @@ -46,7 +46,7 @@ }, "dependencies": { "@microsoft/applicationinsights-web": "^3.3.2", - "@microsoft/feature-management": "2.0.0" + "@microsoft/feature-management": "2.0.1" } } \ No newline at end of file diff --git a/src/feature-management-applicationinsights-browser/src/version.ts b/src/feature-management-applicationinsights-browser/src/version.ts index b4709c9..e71c134 100644 --- a/src/feature-management-applicationinsights-browser/src/version.ts +++ b/src/feature-management-applicationinsights-browser/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "2.0.0"; +export const VERSION = "2.0.1"; diff --git a/src/feature-management-applicationinsights-node/package.json b/src/feature-management-applicationinsights-node/package.json index 21de0fd..4fb4334 100644 --- a/src/feature-management-applicationinsights-node/package.json +++ b/src/feature-management-applicationinsights-node/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/feature-management-applicationinsights-node", - "version": "2.0.0", + "version": "2.0.1", "description": "Feature Management Application Insights Plugin for Node.js provides a solution for sending feature flag evaluation events produced by the Feature Management library.", "main": "./dist/commonjs/index.js", "module": "./dist/esm/index.js", @@ -45,7 +45,7 @@ }, "dependencies": { "applicationinsights": "^2.9.6", - "@microsoft/feature-management": "2.0.0" + "@microsoft/feature-management": "2.0.1" } } \ No newline at end of file diff --git a/src/feature-management-applicationinsights-node/src/version.ts b/src/feature-management-applicationinsights-node/src/version.ts index b4709c9..e71c134 100644 --- a/src/feature-management-applicationinsights-node/src/version.ts +++ b/src/feature-management-applicationinsights-node/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "2.0.0"; +export const VERSION = "2.0.1"; diff --git a/src/feature-management/package-lock.json b/src/feature-management/package-lock.json index 74c975d..76a28af 100644 --- a/src/feature-management/package-lock.json +++ b/src/feature-management/package-lock.json @@ -1,12 +1,12 @@ { "name": "@microsoft/feature-management", - "version": "2.0.0", + "version": "2.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@microsoft/feature-management", - "version": "2.0.0", + "version": "2.0.1", "license": "MIT", "devDependencies": { "@playwright/test": "^1.46.1", diff --git a/src/feature-management/package.json b/src/feature-management/package.json index ea8ed6f..fd4d50c 100644 --- a/src/feature-management/package.json +++ b/src/feature-management/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/feature-management", - "version": "2.0.0", + "version": "2.0.1", "description": "Feature Management is a library for enabling/disabling features at runtime. Developers can use feature flags in simple use cases like conditional statement to more advanced scenarios like conditionally adding routes.", "main": "./dist/commonjs/index.js", "module": "./dist/esm/index.js", diff --git a/src/feature-management/src/version.ts b/src/feature-management/src/version.ts index aaae469..e784648 100644 --- a/src/feature-management/src/version.ts +++ b/src/feature-management/src/version.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "2.0.0"; +export const VERSION = "2.0.1"; export const EVALUATION_EVENT_VERSION = "1.0.0"; From 3ced7afbd6527d70cd0eb9468bffb028e92f8221 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 13:52:09 +0800 Subject: [PATCH 5/9] Bump serialize-javascript and mocha in /src/feature-management (#101) Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) to 6.0.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together. Updates `serialize-javascript` from 6.0.0 to 6.0.2 - [Release notes](https://github.com/yahoo/serialize-javascript/releases) - [Commits](https://github.com/yahoo/serialize-javascript/compare/v6.0.0...v6.0.2) Updates `mocha` from 10.2.0 to 10.8.2 - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v10.2.0...v10.8.2) --- updated-dependencies: - dependency-name: serialize-javascript dependency-type: indirect - dependency-name: mocha dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/feature-management/package-lock.json | 188 ++++++++++------------- 1 file changed, 83 insertions(+), 105 deletions(-) diff --git a/src/feature-management/package-lock.json b/src/feature-management/package-lock.json index 76a28af..25405ed 100644 --- a/src/feature-management/package-lock.json +++ b/src/feature-management/package-lock.json @@ -20,7 +20,7 @@ "eslint": "^8.56.0", "mocha": "^10.2.0", "rimraf": "^5.0.5", - "rollup": "^4.9.4", + "rollup": "^4.22.4", "rollup-plugin-dts": "^6.1.0", "tslib": "^2.6.2", "typescript": "^5.3.3" @@ -1028,10 +1028,11 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1308,12 +1309,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1355,10 +1357,11 @@ "dev": true }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -2259,32 +2262,32 @@ } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -2292,49 +2295,45 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2342,21 +2341,6 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -2373,22 +2357,11 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -2648,6 +2621,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -2825,7 +2799,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/semver": { "version": "7.5.4", @@ -2843,10 +2818,11 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -3096,10 +3072,11 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -3176,10 +3153,11 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -3212,4 +3190,4 @@ } } } -} \ No newline at end of file +} From 00794c6326ebdc9f0aa71205e1af1631099ee81b Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Wed, 12 Feb 2025 14:06:57 +0800 Subject: [PATCH 6/9] add testcases & remove unused code (#94) --- .../test/featureManager.test.ts | 74 ++- .../test/sampleFeatureFlags.ts | 532 ------------------ .../test/sampleVariantFeatureFlags.ts | 221 ++++++++ src/feature-management/test/variant.test.ts | 34 +- 4 files changed, 309 insertions(+), 552 deletions(-) delete mode 100644 src/feature-management/test/sampleFeatureFlags.ts create mode 100644 src/feature-management/test/sampleVariantFeatureFlags.ts diff --git a/src/feature-management/test/featureManager.test.ts b/src/feature-management/test/featureManager.test.ts index 4c235b6..f7f6daa 100644 --- a/src/feature-management/test/featureManager.test.ts +++ b/src/feature-management/test/featureManager.test.ts @@ -52,7 +52,7 @@ describe("feature manager", () => { expect(featureFlags[1]).to.eq("Beta"); }); - it("should fail when feature flag is invalid", async () => { + it("should fail when feature flag id is invalid", async () => { const dataSource = new Map(); dataSource.set("feature_management", { feature_flags: [ @@ -111,7 +111,7 @@ describe("feature manager", () => { ]); }); - it("should evaluate features with conditions", () => { + it("should fail when feature flag is invalid", () => { const dataSource = new Map(); dataSource.set("feature_management", { feature_flags: [ @@ -178,6 +178,74 @@ describe("feature manager", () => { ]); }); - it("should evaluate features with conditions"); + it("should evaluate client filters based on requirement type", () => { + const jsonObject = { + "feature_management": { + "feature_flags": [ + { + "id": "AllFeature", + "enabled": true, + "conditions": { + "requirement_type": "All", + "client_filters": [ + { + "name": "Microsoft.TimeWindow", + "parameters": { + "Start": "Tue, 4 Feb 2025 16:00:00 GMT" + } + }, + { + "name": "Microsoft.Targeting", + "parameters": { + "Audience": { + "Users": [ "Alice" ], + "Exclusion": { + "Users": [ "Dave" ] + } + } + } + } + ] + } + }, + { + "id": "AnyFeature", + "enabled": true, + "conditions": { + // "requirement_type": "Any", + "client_filters": [ + { + "name": "Microsoft.TimeWindow", + "parameters": { + "Start": "Tue, 4 Feb 2025 16:00:00 GMT" + } + }, + { + "name": "Microsoft.Targeting", + "parameters": { + "Audience": { + "Users": [ "Alice" ], + "Exclusion": { + "Users": [ "Dave" ] + } + } + } + } + ] + } + } + ] + } + }; + + const provider = new ConfigurationObjectFeatureFlagProvider(jsonObject); + const featureManager = new FeatureManager(provider); + return Promise.all([ + expect(featureManager.isEnabled("AllFeature", {userId: "Alice"})).eventually.eq(true), + expect(featureManager.isEnabled("AllFeature", {userId: "Dave"})).eventually.eq(false), + expect(featureManager.isEnabled("AnyFeature", {userId: "Dave"})).eventually.eq(true) + ]); + }); + it("should override default filters with custom filters"); }); diff --git a/src/feature-management/test/sampleFeatureFlags.ts b/src/feature-management/test/sampleFeatureFlags.ts deleted file mode 100644 index 85f69b0..0000000 --- a/src/feature-management/test/sampleFeatureFlags.ts +++ /dev/null @@ -1,532 +0,0 @@ -export enum Features { - VariantFeatureDefaultDisabled = "VariantFeatureDefaultDisabled", - VariantFeatureDefaultEnabled = "VariantFeatureDefaultEnabled", - VariantFeaturePercentileOn = "VariantFeaturePercentileOn", - VariantFeaturePercentileOff = "VariantFeaturePercentileOff", - VariantFeatureAlwaysOff = "VariantFeatureAlwaysOff", - VariantFeatureUser = "VariantFeatureUser", - VariantFeatureGroup = "VariantFeatureGroup", - VariantFeatureNoVariants = "VariantFeatureNoVariants", - VariantFeatureNoAllocation = "VariantFeatureNoAllocation", - VariantFeatureAlwaysOffNoAllocation = "VariantFeatureAlwaysOffNoAllocation", - VariantFeatureBothConfigurations = "VariantFeatureBothConfigurations", - VariantFeatureInvalidStatusOverride = "VariantFeatureInvalidStatusOverride", - VariantFeatureInvalidFromTo = "VariantFeatureInvalidFromTo", - VariantImplementationFeature = "VariantImplementationFeature", -} - -export const featureFlagsConfigurationObject = { - "feature_management": { - "feature_flags": [ - { - "id": "OnTestFeature", - "enabled": true - }, - { - "id": "OffTestFeature", - "enabled": false - }, - { - "id": "ConditionalFeature", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "Test", - "parameters": { - "P1": "V1" - } - } - ] - } - }, - { - "id": "ContextualFeature", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "ContextualTest", - "parameters": { - "AllowedAccounts": [ - "abc" - ] - } - } - ] - } - }, - { - "id": "AnyFilterFeature", - "enabled": true, - "conditions": { - "requirement_type": "Any", - "client_filters": [ - { - "name": "Test", - "parameters": { - "Id": "1" - } - }, - { - "name": "Test", - "parameters": { - "Id": "2" - } - } - ] - } - }, - { - "id": "AllFilterFeature", - "enabled": true, - "conditions": { - "requirement_type": "All", - "client_filters": [ - { - "name": "Test", - "parameters": { - "Id": "1" - } - }, - { - "name": "Test", - "parameters": { - "Id": "2" - } - } - ] - } - }, - { - "id": "FeatureUsesFiltersWithDuplicatedAlias", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "DuplicatedFilterName" - }, - { - "name": "Percentage", - "parameters": { - "Value": 100 - } - } - ] - } - }, - { - "id": "TargetingTestFeature", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "Targeting", - "parameters": { - "Audience": { - "Users": [ - "Jeff", - "Alicia" - ], - "Groups": [ - { - "Name": "Ring0", - "RolloutPercentage": 100 - }, - { - "Name": "Ring1", - "RolloutPercentage": 50 - } - ], - "DefaultRolloutPercentage": 20 - } - } - } - ] - } - }, - { - "id": "TargetingTestFeatureWithExclusion", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "Targeting", - "parameters": { - "Audience": { - "Users": [ - "Jeff", - "Alicia" - ], - "Groups": [ - { - "Name": "Ring0", - "RolloutPercentage": 100 - }, - { - "Name": "Ring1", - "RolloutPercentage": 50 - } - ], - "DefaultRolloutPercentage": 20, - "Exclusion": { - "Users": [ - "Jeff" - ], - "Groups": [ - "Ring0", - "Ring2" - ] - } - } - } - } - ] - } - }, - { - "id": "CustomFilterFeature", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "CustomTargetingFilter", - "parameters": { - "Audience": { - "Users": [ - "Jeff" - ] - } - } - } - ] - } - }, - { - "id": "VariantFeaturePercentileOn", - "enabled": true, - "variants": [ - { - "name": "Big", - "status_override": "Disabled" - } - ], - "allocation": { - "percentile": [ - { - "variant": "Big", - "from": 0, - "to": 50 - } - ], - "seed": "1234" - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeaturePercentileOff", - "enabled": true, - "variants": [ - { - "name": "Big" - } - ], - "allocation": { - "percentile": [ - { - "variant": "Big", - "from": 0, - "to": 50 - } - ], - "seed": "12345" - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureAlwaysOff", - "enabled": false, - "variants": [ - { - "name": "Big" - } - ], - "allocation": { - "percentile": [ - { - "variant": "Big", - "from": 0, - "to": 100 - } - ], - "seed": "12345" - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureDefaultDisabled", - "enabled": false, - "variants": [ - { - "name": "Small", - "configuration_value": "300px" - } - ], - "allocation": { - "default_when_disabled": "Small" - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureDefaultEnabled", - "enabled": true, - "variants": [ - { - "name": "Medium", - "configuration_value": { - "Size": "450px", - "Color": "Purple" - } - }, - { - "name": "Small", - "configuration_value": "300px" - } - ], - "allocation": { - "default_when_enabled": "Medium", - "user": [ - { - "variant": "Small", - "users": [ - "Jeff" - ] - } - ] - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureUser", - "enabled": true, - "variants": [ - { - "name": "Small", - "configuration_value": "300px" - } - ], - "allocation": { - "user": [ - { - "variant": "Small", - "users": [ - "Marsha" - ] - } - ] - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureGroup", - "enabled": true, - "variants": [ - { - "name": "Small", - "configuration_value": "300px" - } - ], - "allocation": { - "group": [ - { - "variant": "Small", - "groups": [ - "Group1" - ] - } - ] - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureNoVariants", - "enabled": true, - "variants": [], - "allocation": { - "user": [ - { - "variant": "Small", - "users": [ - "Marsha" - ] - } - ] - }, - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureNoAllocation", - "enabled": true, - "variants": [ - { - "name": "Small", - "configuration_value": "300px" - } - ], - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureAlwaysOffNoAllocation", - "enabled": false, - "variants": [ - { - "name": "Small", - "configuration_value": "300px" - } - ], - "telemetry": { - "enabled": true - } - }, - { - "id": "VariantFeatureBothConfigurations", - "enabled": true, - "variants": [ - { - "name": "Small", - "configuration_value": "600px" - } - ], - "allocation": { - "default_when_enabled": "Small" - } - }, - { - "id": "VariantFeatureInvalidStatusOverride", - "enabled": true, - "variants": [ - { - "name": "Small", - "configuration_value": "300px", - "status_override": "InvalidValue" - } - ], - "allocation": { - "default_when_enabled": "Small" - } - }, - { - "id": "VariantFeatureInvalidFromTo", - "enabled": true, - "variants": [ - { - "name": "Small", - "configuration_value": "300px" - } - ], - "allocation": { - "percentile": [ - { - "variant": "Small", - "from": "Invalid", - "to": "Invalid" - } - ] - } - }, - { - "id": "VariantImplementationFeature", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "Targeting", - "parameters": { - "Audience": { - "Users": [ - "UserOmega", - "UserSigma", - "UserBeta" - ] - } - } - } - ] - }, - "variants": [ - { - "name": "AlgorithmBeta" - }, - { - "name": "Sigma", - "configuration_value": "AlgorithmSigma" - }, - { - "name": "Omega" - } - ], - "allocation": { - "user": [ - { - "variant": "AlgorithmBeta", - "users": [ - "UserBeta" - ] - }, - { - "variant": "Omega", - "users": [ - "UserOmega" - ] - }, - { - "variant": "Sigma", - "users": [ - "UserSigma" - ] - } - ] - } - }, - { - "id": "OnTelemetryTestFeature", - "enabled": true, - "telemetry": { - "enabled": true, - "metadata": { - "Tags.Tag1": "Tag1Value", - "Tags.Tag2": "Tag2Value", - "Etag": "EtagValue", - "Label": "LabelValue" - } - } - }, - { - "id": "OffTelemetryTestFeature", - "enabled": false, - "telemetry": { - "enabled": true - } - } - ] - } -}; - diff --git a/src/feature-management/test/sampleVariantFeatureFlags.ts b/src/feature-management/test/sampleVariantFeatureFlags.ts new file mode 100644 index 0000000..21f0020 --- /dev/null +++ b/src/feature-management/test/sampleVariantFeatureFlags.ts @@ -0,0 +1,221 @@ +export enum Features { + VariantFeatureDefaultDisabled = "VariantFeatureDefaultDisabled", + VariantFeatureDefaultEnabled = "VariantFeatureDefaultEnabled", + VariantFeaturePercentileOn = "VariantFeaturePercentileOn", + VariantFeaturePercentileOff = "VariantFeaturePercentileOff", + VariantFeatureUser = "VariantFeatureUser", + VariantFeatureGroup = "VariantFeatureGroup", + VariantFeatureNoVariants = "VariantFeatureNoVariants", + VariantFeatureNoAllocation = "VariantFeatureNoAllocation", + VariantFeatureInvalidStatusOverride = "VariantFeatureInvalidStatusOverride", + VariantFeatureInvalidFromTo = "VariantFeatureInvalidFromTo", +} + +export const featureFlagsConfigurationObject = { + "feature_management": { + "feature_flags": [ + { + "id": "VariantFeaturePercentileOn", + "enabled": true, + "variants": [ + { + "name": "Big", + "status_override": "Disabled" + } + ], + "allocation": { + "percentile": [ + { + "variant": "Big", + "from": 0, + "to": 50 + } + ], + "seed": "1234" + }, + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeaturePercentileOff", + "enabled": true, + "variants": [ + { + "name": "Big" + } + ], + "allocation": { + "percentile": [ + { + "variant": "Big", + "from": 0, + "to": 50 + } + ], + "seed": "12345" + }, + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeatureDefaultDisabled", + "enabled": false, + "variants": [ + { + "name": "Small", + "configuration_value": "300px" + } + ], + "allocation": { + "default_when_disabled": "Small" + }, + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeatureDefaultEnabled", + "enabled": true, + "variants": [ + { + "name": "Medium", + "configuration_value": { + "Size": "450px", + "Color": "Purple" + } + }, + { + "name": "Small", + "configuration_value": "300px" + } + ], + "allocation": { + "default_when_enabled": "Medium", + "user": [ + { + "variant": "Small", + "users": [ + "Jeff" + ] + } + ] + }, + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeatureUser", + "enabled": true, + "variants": [ + { + "name": "Small", + "configuration_value": "300px" + } + ], + "allocation": { + "user": [ + { + "variant": "Small", + "users": [ + "Marsha" + ] + } + ] + }, + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeatureGroup", + "enabled": true, + "variants": [ + { + "name": "Small", + "configuration_value": "300px" + } + ], + "allocation": { + "group": [ + { + "variant": "Small", + "groups": [ + "Group1" + ] + } + ] + }, + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeatureNoVariants", + "enabled": true, + "variants": [], + "allocation": { + "user": [ + { + "variant": "Small", + "users": [ + "Marsha" + ] + } + ] + }, + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeatureNoAllocation", + "enabled": true, + "variants": [ + { + "name": "Small", + "configuration_value": "300px" + } + ], + "telemetry": { + "enabled": true + } + }, + { + "id": "VariantFeatureInvalidStatusOverride", + "enabled": true, + "variants": [ + { + "name": "Small", + "configuration_value": "300px", + "status_override": "InvalidValue" + } + ], + "allocation": { + "default_when_enabled": "Small" + } + }, + { + "id": "VariantFeatureInvalidFromTo", + "enabled": true, + "variants": [ + { + "name": "Small", + "configuration_value": "300px" + } + ], + "allocation": { + "percentile": [ + { + "variant": "Small", + "from": "Invalid", + "to": "Invalid" + } + ] + } + } + ] + } +}; diff --git a/src/feature-management/test/variant.test.ts b/src/feature-management/test/variant.test.ts index ddfd90f..118fc03 100644 --- a/src/feature-management/test/variant.test.ts +++ b/src/feature-management/test/variant.test.ts @@ -4,7 +4,7 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "../"; -import { Features, featureFlagsConfigurationObject } from "./sampleFeatureFlags.js"; +import { Features, featureFlagsConfigurationObject } from "./sampleVariantFeatureFlags.js"; chai.use(chaiAsPromised); const expect = chai.expect; @@ -20,35 +20,35 @@ describe("feature variant", () => { describe("valid scenarios", () => { const context = { userId: "Marsha", groups: ["Group1"] }; - it("default allocation with disabled feature", async () => { + it("should perform default allocation with disabled feature", async () => { const variant = await featureManager.getVariant(Features.VariantFeatureDefaultDisabled, context); expect(variant).not.to.be.undefined; expect(variant?.name).eq("Small"); expect(variant?.configuration).eq("300px"); }); - it("default allocation with enabled feature", async () => { + it("should perform default allocation with enabled feature", async () => { const variant = await featureManager.getVariant(Features.VariantFeatureDefaultEnabled, context); expect(variant).not.to.be.undefined; expect(variant?.name).eq("Medium"); expect(variant?.configuration).deep.eq({ Size: "450px", Color: "Purple" }); }); - it("user allocation", async () => { + it("should perform user allocation", async () => { const variant = await featureManager.getVariant(Features.VariantFeatureUser, context); expect(variant).not.to.be.undefined; expect(variant?.name).eq("Small"); expect(variant?.configuration).eq("300px"); }); - it("group allocation", async () => { + it("should perform group allocation", async () => { const variant = await featureManager.getVariant(Features.VariantFeatureGroup, context); expect(variant).not.to.be.undefined; expect(variant?.name).eq("Small"); expect(variant?.configuration).eq("300px"); }); - it("percentile allocation with seed", async () => { + it("should perform percentile allocation with seed", async () => { const variant = await featureManager.getVariant(Features.VariantFeaturePercentileOn, context); expect(variant).not.to.be.undefined; expect(variant?.name).eq("Big"); @@ -57,7 +57,7 @@ describe("feature variant", () => { expect(variant2).to.be.undefined; }); - it("overwrite enabled status", async () => { + it("should overwrite enabled status", async () => { const enabledStatus = await featureManager.isEnabled(Features.VariantFeaturePercentileOn, context); expect(enabledStatus).to.be.false; // featureFlag.enabled = true, overridden to false by variant `Big`. }); @@ -67,27 +67,27 @@ describe("feature variant", () => { describe("invalid scenarios", () => { const context = { userId: "Jeff" }; - it("return undefined when no variants are specified", async () => { + it("should return undefined when no variants are specified", async () => { const variant = await featureManager.getVariant(Features.VariantFeatureNoVariants, context); expect(variant).to.be.undefined; }); - it("return undefined when no allocation is specified", async () => { + it("should return undefined when no allocation is specified", async () => { const variant = await featureManager.getVariant(Features.VariantFeatureNoAllocation, context); expect(variant).to.be.undefined; }); - it("only support configuration value", async () => { - const variant = await featureManager.getVariant(Features.VariantFeatureBothConfigurations, context); - expect(variant).not.to.be.undefined; - expect(variant?.configuration).eq("600px"); - }); - // requires IFeatureFlagProvider to throw an exception on validation - it("throw exception for invalid StatusOverride value"); + it("should throw exception for invalid StatusOverride value", async () => { + await expect(featureManager.getVariant(Features.VariantFeatureInvalidStatusOverride, context)) + .eventually.rejectedWith("Invalid feature flag: VariantFeatureInvalidStatusOverride. Variant 'status_override' must be 'None', 'Enabled', or 'Disabled'."); + }); // requires IFeatureFlagProvider to throw an exception on validation - it("throw exception for invalid doubles From and To in the Percentile section"); + it("should throw exception for invalid doubles From and To in the Percentile section", async () => { + await expect(featureManager.getVariant(Features.VariantFeatureInvalidFromTo, context)) + .eventually.rejectedWith("Invalid feature flag: VariantFeatureInvalidFromTo. Percentile allocation 'from' must be a number between 0 and 100."); + }); }); From f9192432c85a168e25e384273769cd67462a8af2 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Tue, 18 Feb 2025 14:25:07 +0800 Subject: [PATCH 7/9] update readme (#102) --- README.md | 20 ++++++++++++----- .../README.md | 4 +++- .../README.md | 6 +++-- src/feature-management/README.md | 22 +++++++++++++------ 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 7ddcdc6..b9e56bf 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,19 @@ [![feature-management](https://img.shields.io/npm/v/@microsoft/feature-management?label=@microsoft/feature-management)](https://www.npmjs.com/package/@microsoft/feature-management) -Feature Management is a library for enabling/disabling features at runtime. -Developers can use feature flags in simple use cases like conditional statement to more advanced scenarios like conditionally adding routes. +Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common .NET code patterns to make exposing these features possible. ## Getting Started -### Prerequisites +[Azure App Configuration Quickstart](https://learn.microsoft.com/azure/azure-app-configuration/quickstart-feature-flag-javascript): A quickstart guide about how to integrate feature flags from Azure App Configuration into your JavaScript applications. -- Node.js LTS version +[Feature Overview](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-overview#feature-development-status): This document provides a feature status overview. + +[Feature Reference](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-javascript-reference): This document provides a full feature rundown. ### Usage -You can use feature flags from the Azure App Configuration service, local files or any other sources. +You can use feature flags from the Azure App Configuration service, local files or any other sources. For more information, please go to [Feature flag configuration](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-javascript-reference#feature-flag-configuration). #### Use feature flags from Azure App Configuration @@ -21,7 +22,9 @@ The App Configuration JavaScript provider provides feature flags in as a `Map` o A builtin `ConfigurationMapFeatureFlagProvider` helps to load feature flags in this case. ```js -const appConfig = await load(connectionString, {featureFlagOptions}); // load feature flags from Azure App Configuration service +import { load } from "@azure/app-configuration-provider"; +import { FeatureManager, ConfigurationMapFeatureFlagProvider } from "@microsoft/feature-management"; +const appConfig = await load("", {featureFlagOptions}); // load feature flags from Azure App Configuration service const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig); const featureManager = new FeatureManager(featureProvider); const isAlphaEnabled = await featureManager.isEnabled("Alpha"); @@ -54,6 +57,7 @@ Content of `sample.json`: Load feature flags from `sample.json` file. ```js +import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "@microsoft/feature-management"; const config = JSON.parse(await fs.readFile("path/to/sample.json")); const featureProvider = new ConfigurationObjectFeatureFlagProvider(config); const featureManager = new FeatureManager(featureProvider); @@ -61,6 +65,10 @@ const isAlphaEnabled = await featureManager.isEnabled("Alpha"); console.log("Feature Alpha is:", isAlphaEnabled); ``` +## Examples + +See code snippets under [examples/](./examples/) folder. + ## Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a diff --git a/src/feature-management-applicationinsights-browser/README.md b/src/feature-management-applicationinsights-browser/README.md index bf04bf0..e55f448 100644 --- a/src/feature-management-applicationinsights-browser/README.md +++ b/src/feature-management-applicationinsights-browser/README.md @@ -1,9 +1,11 @@ # Microsoft Feature Management Application Insights Plugin for Browser -Feature Management Application Insights Plugin for Browser provides a solution for sending feature flag evaluation events produced by the Feature Management library. +Feature Management Application Insights Plugin for Browser provides a solution for sending feature flag evaluation telemetry produced by the [`@microsoft/feature-management`](https://www.npmjs.com/package/@microsoft/feature-management) library. ## Getting Started +For more information, please go to [Feature reference](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-javascript-reference#application-insights-integration). + ### Usage ``` javascript diff --git a/src/feature-management-applicationinsights-node/README.md b/src/feature-management-applicationinsights-node/README.md index b08f98a..4dc36d8 100644 --- a/src/feature-management-applicationinsights-node/README.md +++ b/src/feature-management-applicationinsights-node/README.md @@ -1,13 +1,15 @@ # Microsoft Feature Management Application Insights Plugin for Node -Feature Management Application Insights Plugin for Node provides a solution for sending feature flag evaluation events produced by the Feature Management library. +Feature Management Application Insights Plugin for Node provides a solution for sending feature flag evaluation telemetry produced by the [`@microsoft/feature-management`](https://www.npmjs.com/package/@microsoft/feature-management) library. ## Getting Started +For more information, please go to [Feature reference](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-javascript-reference#application-insights-integration). + ### Prerequisites - Node.js LTS version -- `applicationinsights` SDK v2(classic) +- `applicationinsights` SDK 2.x (classic) ### Usage diff --git a/src/feature-management/README.md b/src/feature-management/README.md index 54aa97a..b9e56bf 100644 --- a/src/feature-management/README.md +++ b/src/feature-management/README.md @@ -2,18 +2,19 @@ [![feature-management](https://img.shields.io/npm/v/@microsoft/feature-management?label=@microsoft/feature-management)](https://www.npmjs.com/package/@microsoft/feature-management) -Feature Management is a library for enabling/disabling features at runtime. -Developers can use feature flags in simple use cases like conditional statement to more advanced scenarios like conditionally adding routes. +Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common .NET code patterns to make exposing these features possible. ## Getting Started -### Prerequisites +[Azure App Configuration Quickstart](https://learn.microsoft.com/azure/azure-app-configuration/quickstart-feature-flag-javascript): A quickstart guide about how to integrate feature flags from Azure App Configuration into your JavaScript applications. -- Node.js LTS version +[Feature Overview](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-overview#feature-development-status): This document provides a feature status overview. + +[Feature Reference](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-javascript-reference): This document provides a full feature rundown. ### Usage -You can use feature flags from the Azure App Configuration service, local files or any other sources. +You can use feature flags from the Azure App Configuration service, local files or any other sources. For more information, please go to [Feature flag configuration](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-javascript-reference#feature-flag-configuration). #### Use feature flags from Azure App Configuration @@ -21,7 +22,9 @@ The App Configuration JavaScript provider provides feature flags in as a `Map` o A builtin `ConfigurationMapFeatureFlagProvider` helps to load feature flags in this case. ```js -const appConfig = load(connectionString, {featureFlagOptions}); // load feature flags from Azure App Configuration service +import { load } from "@azure/app-configuration-provider"; +import { FeatureManager, ConfigurationMapFeatureFlagProvider } from "@microsoft/feature-management"; +const appConfig = await load("", {featureFlagOptions}); // load feature flags from Azure App Configuration service const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig); const featureManager = new FeatureManager(featureProvider); const isAlphaEnabled = await featureManager.isEnabled("Alpha"); @@ -42,7 +45,7 @@ Content of `sample.json`: { "id": "Alpha", "description": "", - "enabled": "true", + "enabled": true, "conditions": { "client_filters": [] } @@ -54,6 +57,7 @@ Content of `sample.json`: Load feature flags from `sample.json` file. ```js +import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "@microsoft/feature-management"; const config = JSON.parse(await fs.readFile("path/to/sample.json")); const featureProvider = new ConfigurationObjectFeatureFlagProvider(config); const featureManager = new FeatureManager(featureProvider); @@ -61,6 +65,10 @@ const isAlphaEnabled = await featureManager.isEnabled("Alpha"); console.log("Feature Alpha is:", isAlphaEnabled); ``` +## Examples + +See code snippets under [examples/](./examples/) folder. + ## Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a From 6477614f97c89346918b3bb347b5885ee9644124 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Mon, 24 Feb 2025 12:31:05 +0800 Subject: [PATCH 8/9] Merge pull request #106 from microsoft/zhiyuanliang/fix-typo-in-README Fix typo in README --- README.md | 2 +- src/feature-management/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b9e56bf..5f78a40 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![feature-management](https://img.shields.io/npm/v/@microsoft/feature-management?label=@microsoft/feature-management)](https://www.npmjs.com/package/@microsoft/feature-management) -Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common .NET code patterns to make exposing these features possible. +Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common JavaScript code patterns to make exposing these features possible. ## Getting Started diff --git a/src/feature-management/README.md b/src/feature-management/README.md index b9e56bf..5f78a40 100644 --- a/src/feature-management/README.md +++ b/src/feature-management/README.md @@ -2,7 +2,7 @@ [![feature-management](https://img.shields.io/npm/v/@microsoft/feature-management?label=@microsoft/feature-management)](https://www.npmjs.com/package/@microsoft/feature-management) -Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common .NET code patterns to make exposing these features possible. +Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common JavaScript code patterns to make exposing these features possible. ## Getting Started From 0d14ad73768474be5a90646a98b2f22453171d27 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Mon, 24 Feb 2025 12:49:51 +0800 Subject: [PATCH 9/9] version bump 2.0.2 (#108) --- .../package.json | 4 ++-- .../src/version.ts | 2 +- src/feature-management-applicationinsights-node/package.json | 4 ++-- .../src/version.ts | 2 +- src/feature-management/package-lock.json | 4 ++-- src/feature-management/package.json | 2 +- src/feature-management/src/version.ts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/feature-management-applicationinsights-browser/package.json b/src/feature-management-applicationinsights-browser/package.json index 33d3f08..9bab599 100644 --- a/src/feature-management-applicationinsights-browser/package.json +++ b/src/feature-management-applicationinsights-browser/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/feature-management-applicationinsights-browser", - "version": "2.0.1", + "version": "2.0.2", "description": "Feature Management Application Insights Plugin for Browser provides a solution for sending feature flag evaluation events produced by the Feature Management library.", "main": "./dist/esm/index.js", "module": "./dist/esm/index.js", @@ -46,7 +46,7 @@ }, "dependencies": { "@microsoft/applicationinsights-web": "^3.3.2", - "@microsoft/feature-management": "2.0.1" + "@microsoft/feature-management": "2.0.2" } } \ No newline at end of file diff --git a/src/feature-management-applicationinsights-browser/src/version.ts b/src/feature-management-applicationinsights-browser/src/version.ts index e71c134..92cdac8 100644 --- a/src/feature-management-applicationinsights-browser/src/version.ts +++ b/src/feature-management-applicationinsights-browser/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "2.0.1"; +export const VERSION = "2.0.2"; diff --git a/src/feature-management-applicationinsights-node/package.json b/src/feature-management-applicationinsights-node/package.json index 4fb4334..f6701d6 100644 --- a/src/feature-management-applicationinsights-node/package.json +++ b/src/feature-management-applicationinsights-node/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/feature-management-applicationinsights-node", - "version": "2.0.1", + "version": "2.0.2", "description": "Feature Management Application Insights Plugin for Node.js provides a solution for sending feature flag evaluation events produced by the Feature Management library.", "main": "./dist/commonjs/index.js", "module": "./dist/esm/index.js", @@ -45,7 +45,7 @@ }, "dependencies": { "applicationinsights": "^2.9.6", - "@microsoft/feature-management": "2.0.1" + "@microsoft/feature-management": "2.0.2" } } \ No newline at end of file diff --git a/src/feature-management-applicationinsights-node/src/version.ts b/src/feature-management-applicationinsights-node/src/version.ts index e71c134..92cdac8 100644 --- a/src/feature-management-applicationinsights-node/src/version.ts +++ b/src/feature-management-applicationinsights-node/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "2.0.1"; +export const VERSION = "2.0.2"; diff --git a/src/feature-management/package-lock.json b/src/feature-management/package-lock.json index 25405ed..f399cf0 100644 --- a/src/feature-management/package-lock.json +++ b/src/feature-management/package-lock.json @@ -1,12 +1,12 @@ { "name": "@microsoft/feature-management", - "version": "2.0.1", + "version": "2.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@microsoft/feature-management", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "devDependencies": { "@playwright/test": "^1.46.1", diff --git a/src/feature-management/package.json b/src/feature-management/package.json index fd4d50c..6bd0628 100644 --- a/src/feature-management/package.json +++ b/src/feature-management/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/feature-management", - "version": "2.0.1", + "version": "2.0.2", "description": "Feature Management is a library for enabling/disabling features at runtime. Developers can use feature flags in simple use cases like conditional statement to more advanced scenarios like conditionally adding routes.", "main": "./dist/commonjs/index.js", "module": "./dist/esm/index.js", diff --git a/src/feature-management/src/version.ts b/src/feature-management/src/version.ts index e784648..6a06472 100644 --- a/src/feature-management/src/version.ts +++ b/src/feature-management/src/version.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "2.0.1"; +export const VERSION = "2.0.2"; export const EVALUATION_EVENT_VERSION = "1.0.0";