From 300cf06b3658313ceb6ae55b8e46ea02e2dd4637 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:59:15 +0800 Subject: [PATCH 1/7] version bump 1.1.3 (#145) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac1204cd..b265cb5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "1.1.2", + "version": "1.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.1.2", + "version": "1.1.3", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.6.1", diff --git a/package.json b/package.json index 0b493ea3..7ec6f6b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.1.2", + "version": "1.1.3", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index 1c39d36f..91c099f6 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "1.1.2"; +export const VERSION = "1.1.3"; From 6206bc0fd2122075722120871fb22c5e858ffc9a Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:19:38 +0800 Subject: [PATCH 2/7] fix vulnerable package (#149) --- package-lock.json | 158 +++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 85 deletions(-) diff --git a/package-lock.json b/package-lock.json index b265cb5d..e2c6af23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1138,9 +1138,9 @@ } }, "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, "engines": { "node": ">=6" @@ -1425,9 +1425,9 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -1439,11 +1439,11 @@ } }, "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==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1501,9 +1501,9 @@ } }, "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, "engines": { "node": ">=0.3.1" @@ -2573,32 +2573,31 @@ } }, "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, + "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", @@ -2606,10 +2605,6 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha/node_modules/brace-expansion": { @@ -2621,10 +2616,30 @@ "balanced-match": "^1.0.0" } }, + "node_modules/mocha/node_modules/glob": { + "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, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "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, "dependencies": { "brace-expansion": "^2.0.1" @@ -2633,12 +2648,6 @@ "node": ">=10" } }, - "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", @@ -2655,21 +2664,9 @@ } }, "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==" - }, - "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==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -3175,9 +3172,9 @@ } }, "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, "dependencies": { "randombytes": "^2.1.0" @@ -3235,15 +3232,6 @@ "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3477,9 +3465,9 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "node_modules/wrap-ansi": { @@ -3556,9 +3544,9 @@ } }, "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, "engines": { "node": ">=10" From d649dd3fb6951d1c731e26a39da64a91bd9387c9 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:19:54 +0800 Subject: [PATCH 3/7] add lint rule (#151) --- .eslintrc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.eslintrc b/.eslintrc index 27a13ccf..7956229a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -33,6 +33,13 @@ "@typescript-eslint" ], "rules": { + "keyword-spacing": [ + "error", + { + "before": true, + "after": true + } + ], "quotes": [ "error", "double", From 5956b72ab99f640eaa9f95880201b2a9356bf4b3 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Mon, 10 Feb 2025 10:42:14 +0800 Subject: [PATCH 4/7] load all feature flag with no label by default (#158) --- src/AzureAppConfigurationImpl.ts | 4 +-- src/featureManagement/FeatureFlagOptions.ts | 5 ++-- test/featureFlag.test.ts | 29 ++++++++++----------- test/utils/testHelper.ts | 4 +-- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index 916ece49..6d7a4a98 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -898,8 +898,8 @@ function getValidKeyValueSelectors(selectors?: SettingSelector[]): SettingSelect function getValidFeatureFlagSelectors(selectors?: SettingSelector[]): SettingSelector[] { if (selectors === undefined || selectors.length === 0) { - // selectors must be explicitly provided. - throw new Error("Feature flag selectors must be provided."); + // Default selector: key: *, label: \0 + return [{ keyFilter: `${featureFlagPrefix}${KeyFilter.Any}`, labelFilter: LabelFilter.Null }]; } else { selectors.forEach(selector => { selector.keyFilter = `${featureFlagPrefix}${selector.keyFilter}`; diff --git a/src/featureManagement/FeatureFlagOptions.ts b/src/featureManagement/FeatureFlagOptions.ts index eedf9ec7..55ceda4d 100644 --- a/src/featureManagement/FeatureFlagOptions.ts +++ b/src/featureManagement/FeatureFlagOptions.ts @@ -10,16 +10,15 @@ import { SettingSelector } from "../types.js"; export interface FeatureFlagOptions { /** * Specifies whether feature flags will be loaded from Azure App Configuration. - */ enabled: boolean; /** - * Specifies the selectors used to filter feature flags. + * Specifies what feature flags to include in the configuration provider. * * @remarks * keyFilter of selector will be prefixed with "appconfig.featureflag/" when request is sent. - * If no selectors are specified then no feature flags will be retrieved. + * If no selectors are specified then all feature flags with no label will be included. */ selectors?: SettingSelector[]; diff --git a/test/featureFlag.test.ts b/test/featureFlag.test.ts index 2544e617..2d6a7e02 100644 --- a/test/featureFlag.test.ts +++ b/test/featureFlag.test.ts @@ -3,6 +3,7 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; +import { featureFlagContentType } from "@azure/app-configuration"; import { load } from "./exportedApi.js"; import { MAX_TIME_OUT, createMockedConnectionString, createMockedEndpoint, createMockedFeatureFlag, createMockedKeyValue, mockAppConfigurationClientListConfigurationSettings, restoreMocks } from "./utils/testHelper.js"; chai.use(chaiAsPromised); @@ -49,9 +50,9 @@ const mockedKVs = [{ }, { key: ".appconfig.featureflag/variant", value: sampleVariantValue, - contentType: "application/vnd.microsoft.appconfig.ff+json;charset=utf-8", + contentType: featureFlagContentType, }].map(createMockedKeyValue).concat([ - createMockedFeatureFlag("Beta", { enabled: true }), + createMockedFeatureFlag("FlagWithTestLabel", { enabled: true }, {label: "Test"}), createMockedFeatureFlag("Alpha_1", { enabled: true }), createMockedFeatureFlag("Alpha_2", { enabled: false }), createMockedFeatureFlag("Telemetry_1", { enabled: true, telemetry: { enabled: true } }, { etag: "ETag"}), @@ -213,15 +214,22 @@ describe("feature flags", function () { const connectionString = createMockedConnectionString(); const settings = await load(connectionString, { featureFlagOptions: { - enabled: true, - selectors: [{ - keyFilter: "*" - }] + enabled: true } }); expect(settings).not.undefined; expect(settings.get("feature_management")).not.undefined; expect(settings.get("feature_management").feature_flags).not.undefined; + // it should only load feature flags with no label by default + expect((settings.get("feature_management").feature_flags as any[]).find(ff => ff.id === "FlagWithTestLabel")).to.be.undefined; + + const settings2 = await load(connectionString, { + featureFlagOptions: { + enabled: true, + selectors: [ { keyFilter: "*", labelFilter: "Test" } ] + } + }); + expect((settings2.get("feature_management").feature_flags as any[]).find(ff => ff.id === "FlagWithTestLabel")).not.undefined; }); it("should not load feature flags if disabled", async () => { @@ -242,15 +250,6 @@ describe("feature flags", function () { expect(settings.get("feature_management")).undefined; }); - it("should throw error if selectors not specified", async () => { - const connectionString = createMockedConnectionString(); - return expect(load(connectionString, { - featureFlagOptions: { - enabled: true - } - })).eventually.rejectedWith("Feature flag selectors must be provided."); - }); - it("should load feature flags with custom selector", async () => { const connectionString = createMockedConnectionString(); const settings = await load(connectionString, { diff --git a/test/utils/testHelper.ts b/test/utils/testHelper.ts index a5812694..85f7ac80 100644 --- a/test/utils/testHelper.ts +++ b/test/utils/testHelper.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import * as sinon from "sinon"; -import { AppConfigurationClient, ConfigurationSetting } from "@azure/app-configuration"; +import { AppConfigurationClient, ConfigurationSetting, featureFlagContentType } from "@azure/app-configuration"; import { ClientSecretCredential } from "@azure/identity"; import { KeyVaultSecret, SecretClient } from "@azure/keyvault-secrets"; import * as uuid from "uuid"; @@ -240,7 +240,7 @@ const createMockedFeatureFlag = (name: string, flagProps?: any, props?: any) => "client_filters": [] } }, flagProps)), - contentType: "application/vnd.microsoft.appconfig.ff+json;charset=utf-8", + contentType: featureFlagContentType, lastModified: new Date(), tags: {}, etag: uuid.v4(), From ca7c5bbfe6a435ca8cb028fcd938e7cd0c1125d9 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Mon, 10 Feb 2025 17:10:04 +0800 Subject: [PATCH 5/7] Add feature management package version tracing (#153) * add fm package version tracing * update comment * update --- rollup.config.mjs | 2 +- src/AzureAppConfigurationImpl.ts | 21 ++++++++++++++++++++- src/ConfigurationClientManager.ts | 3 +++ src/requestTracing/constants.ts | 4 ++++ src/requestTracing/utils.ts | 7 ++++++- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/rollup.config.mjs b/rollup.config.mjs index 8ad51640..1fa9626f 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -4,7 +4,7 @@ import dts from "rollup-plugin-dts"; export default [ { - external: ["@azure/app-configuration", "@azure/keyvault-secrets", "@azure/core-rest-pipeline", "crypto", "dns/promises"], + external: ["@azure/app-configuration", "@azure/keyvault-secrets", "@azure/core-rest-pipeline", "crypto", "dns/promises", "@microsoft/feature-management"], input: "src/index.ts", output: [ { diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index 6d7a4a98..b89e7a81 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -33,6 +33,7 @@ import { CONDITIONS_KEY_NAME, CLIENT_FILTERS_KEY_NAME } from "./featureManagement/constants.js"; +import { FM_PACKAGE_NAME } from "./requestTracing/constants.js"; import { AzureKeyVaultKeyValueAdapter } from "./keyvault/AzureKeyVaultKeyValueAdapter.js"; import { RefreshTimer } from "./refresh/RefreshTimer.js"; import { RequestTracingOptions, getConfigurationSettingWithTrace, listConfigurationSettingsWithTrace, requestTracingEnabled } from "./requestTracing/utils.js"; @@ -65,6 +66,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { #isInitialLoadCompleted: boolean = false; #isFailoverRequest: boolean = false; #featureFlagTracing: FeatureFlagTracingOptions | undefined; + #fmVersion: string | undefined; // Refresh #refreshInProgress: boolean = false; @@ -184,7 +186,8 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { initialLoadCompleted: this.#isInitialLoadCompleted, replicaCount: this.#clientManager.getReplicaCount(), isFailoverRequest: this.#isFailoverRequest, - featureFlagTracing: this.#featureFlagTracing + featureFlagTracing: this.#featureFlagTracing, + fmVersion: this.#fmVersion }; } @@ -226,6 +229,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { * Loads the configuration store for the first time. */ async load() { + await this.#inspectFmPackage(); await this.#loadSelectedAndWatchedKeyValues(); if (this.#featureFlagEnabled) { await this.#loadFeatureFlags(); @@ -316,6 +320,21 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { return new Disposable(remove); } + /** + * Inspects the feature management package version. + */ + async #inspectFmPackage() { + if (this.#requestTracingEnabled && !this.#fmVersion) { + try { + // get feature management package version + const fmPackage = await import(FM_PACKAGE_NAME); + this.#fmVersion = fmPackage?.VERSION; + } catch (error) { + // ignore the error + } + } + } + async #refreshTasks(): Promise { const refreshTasks: Promise[] = []; if (this.#refreshEnabled) { diff --git a/src/ConfigurationClientManager.ts b/src/ConfigurationClientManager.ts index 92e16a3a..7ad8e597 100644 --- a/src/ConfigurationClientManager.ts +++ b/src/ConfigurationClientManager.ts @@ -85,6 +85,9 @@ export class ConfigurationClientManager { this.#isFailoverable = false; return; } + if (this.#dns) { + return; + } try { this.#dns = await import("dns/promises"); diff --git a/src/requestTracing/constants.ts b/src/requestTracing/constants.ts index 5a88b0fc..74ca58bb 100644 --- a/src/requestTracing/constants.ts +++ b/src/requestTracing/constants.ts @@ -55,6 +55,10 @@ export const FAILOVER_REQUEST_TAG = "Failover"; export const FEATURES_KEY = "Features"; export const LOAD_BALANCE_CONFIGURED_TAG = "LB"; +// Feature management package +export const FM_PACKAGE_NAME = "@microsoft/feature-management"; +export const FM_VERSION_KEY = "FMJsVer"; + // Feature flag usage tracing export const FEATURE_FILTER_TYPE_KEY = "Filter"; export const CUSTOM_FILTER_KEY = "CSTM"; diff --git a/src/requestTracing/utils.ts b/src/requestTracing/utils.ts index b56c460c..2e8b1124 100644 --- a/src/requestTracing/utils.ts +++ b/src/requestTracing/utils.ts @@ -27,7 +27,8 @@ import { REPLICA_COUNT_KEY, FAILOVER_REQUEST_TAG, FEATURES_KEY, - LOAD_BALANCE_CONFIGURED_TAG + LOAD_BALANCE_CONFIGURED_TAG, + FM_VERSION_KEY } from "./constants"; export interface RequestTracingOptions { @@ -37,6 +38,7 @@ export interface RequestTracingOptions { replicaCount: number; isFailoverRequest: boolean; featureFlagTracing: FeatureFlagTracingOptions | undefined; + fmVersion: string | undefined; } // Utils @@ -119,6 +121,9 @@ export function createCorrelationContextHeader(requestTracingOptions: RequestTra if (requestTracingOptions.replicaCount > 0) { keyValues.set(REPLICA_COUNT_KEY, requestTracingOptions.replicaCount.toString()); } + if (requestTracingOptions.fmVersion) { + keyValues.set(FM_VERSION_KEY, requestTracingOptions.fmVersion); + } // Compact tags: Features=LB+... if (appConfigOptions?.loadBalancingEnabled) { From 07026ac7a080d3ef9ddae651494ca6f26e15466c Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:52:15 +0800 Subject: [PATCH 6/7] unify code style (#159) --- src/AzureAppConfigurationImpl.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index b89e7a81..90e283f0 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -919,12 +919,11 @@ function getValidFeatureFlagSelectors(selectors?: SettingSelector[]): SettingSel if (selectors === undefined || selectors.length === 0) { // Default selector: key: *, label: \0 return [{ keyFilter: `${featureFlagPrefix}${KeyFilter.Any}`, labelFilter: LabelFilter.Null }]; - } else { - selectors.forEach(selector => { - selector.keyFilter = `${featureFlagPrefix}${selector.keyFilter}`; - }); - return getValidSelectors(selectors); } + selectors.forEach(selector => { + selector.keyFilter = `${featureFlagPrefix}${selector.keyFilter}`; + }); + return getValidSelectors(selectors); } function isFailoverableError(error: any): boolean { From b2f7727565a7f8048672a7a97a695b0bb7291c8a Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Wed, 12 Feb 2025 13:20:15 +0800 Subject: [PATCH 7/7] version bump 2.0.0 (#161) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a7374571..5ce195df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "2.0.0-preview.2", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "2.0.0-preview.2", + "version": "2.0.0", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.6.1", diff --git a/package.json b/package.json index 16148a76..04b4e526 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "2.0.0-preview.2", + "version": "2.0.0", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index bb9c7aa8..dba07670 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "2.0.0-preview.2"; +export const VERSION = "2.0.0";