From 8c86216e5057ee2f934e78d2b97cf185064ae429 Mon Sep 17 00:00:00 2001 From: MaryanneNjeri Date: Thu, 9 Jul 2026 23:02:35 +0300 Subject: [PATCH 1/7] Minor code fix --- .../azure-app-configuration-importer/src/internal/utils.ts | 4 ++-- .../tests/appConfigurationImporter.spec.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/azure-app-configuration-importer/src/internal/utils.ts b/libraries/azure-app-configuration-importer/src/internal/utils.ts index 9667276..5921751 100644 --- a/libraries/azure-app-configuration-importer/src/internal/utils.ts +++ b/libraries/azure-app-configuration-importer/src/internal/utils.ts @@ -41,7 +41,7 @@ export function isJsonContentType(contentType?: string): boolean { } /** @internal*/ -export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting) { +export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting, configProfile: ConfigurationProfile) { let valueIsEqual: boolean = settingA.value == settingB.value; if (settingA.contentType == featureFlagContentType && @@ -53,7 +53,7 @@ export function isConfigSettingEqual(settingA: SetConfigurationSettingParam c.changeType === ChangeType.Delete); assert.equal(configurationChangesToAdd.length, 0); - assert.equal(configurationChangesToModify.length, 1); + assert.equal(configurationChangesToModify.length, 2); assert.equal(configurationChangesToModify[0].newValue?.key, "app:Settings:FontColor"); assert.equal(configurationChangesToRefresh.length, 2); assert.equal(configurationChangesToDelete.length, 0); @@ -349,7 +349,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () const configurationChangesToDelete = configurationChanges.filter(c => c.changeType === ChangeType.Delete); assert.equal(configurationChangesToAdd.length, 0); - assert.equal(configurationChangesToModify.length, 1); + assert.equal(configurationChangesToModify.length, 2); assert.equal(configurationChangesToModify[0].newValue?.key, "app:Settings:FontColor"); assert.ok(configurationChangesToModify[0].currentValue, "existing setting should be present for diff display"); assert.equal(configurationChangesToRefresh.length, 2); @@ -374,7 +374,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () const configurationChangesToDelete = configurationChanges.filter(c => c.changeType === ChangeType.Delete); assert.equal(configurationChangesToAdd.length, 0); - assert.equal(configurationChangesToModify.length, 1); + assert.equal(configurationChangesToModify.length, 2); assert.equal(configurationChangesToModify[0].newValue?.key, "app:Settings:FontColor"); assert.ok(configurationChangesToModify[0].currentValue, "existing setting should be present for diff display"); assert.equal(configurationChangesToRefresh.length, 0); From 9aa2b2e495a843f8e364ff50a4d8ba9486b988b1 Mon Sep 17 00:00:00 2001 From: MaryanneNjeri Date: Sun, 12 Jul 2026 12:29:04 +0300 Subject: [PATCH 2/7] Add supportDescriptionField property --- .../src/appConfigurationImporter.ts | 2 +- .../src/internal/utils.ts | 5 +- .../configurationChangesSource.ts | 6 +- .../configurationSettingsSource.ts | 7 + .../iterableConfigurationSettingsSource.ts | 3 +- ...adableStreamConfigurationSettingsSource.ts | 3 + .../stringConfigurationSettingsSource.ts | 4 + .../tests/appConfigurationImporter.spec.ts | 10 +- .../tests/util.spec.ts | 132 ++++++++++++------ 9 files changed, 120 insertions(+), 52 deletions(-) diff --git a/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts b/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts index 1ee950b..724af56 100644 --- a/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts +++ b/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts @@ -161,7 +161,7 @@ export class AppConfigurationImporter { // Remove from add list since it already exists toAddKeys.delete(composite); - if (!isConfigSettingEqual(incoming, existing)) { + if (!isConfigSettingEqual(incoming, existing, configSettingsSource.supportsDescriptionField)) { configurationChanges.push({ changeType: ChangeType.Update, currentValue: existing, diff --git a/libraries/azure-app-configuration-importer/src/internal/utils.ts b/libraries/azure-app-configuration-importer/src/internal/utils.ts index 1db487d..5e7b949 100644 --- a/libraries/azure-app-configuration-importer/src/internal/utils.ts +++ b/libraries/azure-app-configuration-importer/src/internal/utils.ts @@ -41,7 +41,7 @@ export function isJsonContentType(contentType?: string): boolean { } /** @internal*/ -export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting, configProfile: ConfigurationProfile) { +export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting, isDescriptionFieldSupported: boolean) { let valueIsEqual: boolean = settingA.value == settingB.value; if (settingA.contentType == featureFlagContentType && @@ -50,10 +50,9 @@ export function isConfigSettingEqual(settingA: SetConfigurationSettingParam; - - constructor(configurationChanges: Array, filterOptions?: ListConfigurationSettingsOptions) { + + constructor(configurationChanges: Array, supportDescriptionField: boolean, filterOptions?: ListConfigurationSettingsOptions) { if (filterOptions && Object.keys(filterOptions).length > 0) { throw new ArgumentError("FilterOptions are not supported for ConfigurationChangesSource."); } + this.supportsDescriptionField = supportDescriptionField; this.configurationChanges = configurationChanges; } diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts index fc23ced..635ed5b 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts @@ -20,6 +20,13 @@ export interface ConfigurationSettingsSource { */ GetConfigurationSettings(): Promise> | Array>; + /** + * Description field supported in the configuration settings source + * + * @returns boolean + */ + supportsDescriptionField: boolean; + /** * Get label and prefix filter * diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts index 65916e9..11a2dfe 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts @@ -18,13 +18,14 @@ import { ArgumentError } from "../errors"; export class IterableConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - + public supportsDescriptionField: boolean; private data: PagedAsyncIterableIterator, ListConfigurationSettingPage, PageSettings>; private options: IterableSourceOptions; constructor(options: IterableSourceOptions) { this.data = options.data; this.options = options; + this.supportsDescriptionField = true; this.FilterOptions = { keyFilter: options.prefix ? options.prefix + "*" : undefined, diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts index 2d67619..167eef3 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts @@ -11,6 +11,7 @@ import { validateOptions} from "../internal/utils"; export class ReadableStreamConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; + public supportsDescriptionField: boolean = false; private options: SourceOptions; private data: ReadableStream | NodeJS.ReadableStream; @@ -24,12 +25,14 @@ export class ReadableStreamConfigurationSettingsSource implements ConfigurationS keyFilter: options.prefix ? options.prefix + "*" : undefined, labelFilter: options.label ? options.label : "\0" }; + this.supportsDescriptionField = false; } else if (options.profile == ConfigurationProfile.KvSet) { this.FilterOptions = { keyFilter: "*", labelFilter: "*" }; + this.supportsDescriptionField = true; } } diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts index 40d489e..a7065a8 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts @@ -24,6 +24,7 @@ import { KvSetConfigurationSettingsConverter } from "../internal/parsers/kvSetCo */ export class StringConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; + public supportsDescriptionField: boolean = false; private options: SourceOptions; private data: string; @@ -37,12 +38,15 @@ export class StringConfigurationSettingsSource implements ConfigurationSettingsS keyFilter: options.prefix ? options.prefix + "*" : undefined, labelFilter: options.label ? options.label : "\0" }; + + this.supportsDescriptionField = false; } else if (options.profile == ConfigurationProfile.KvSet) { this.FilterOptions = { keyFilter: "*", labelFilter: "*" }; + this.supportsDescriptionField = true; } } diff --git a/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts b/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts index eefacfc..aa3a6e7 100644 --- a/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts +++ b/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts @@ -285,7 +285,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () const configurationChangesToDelete = configurationChanges.filter(c => c.changeType === ChangeType.Delete); assert.equal(configurationChangesToAdd.length, 0); - assert.equal(configurationChangesToModify.length, 2); + assert.equal(configurationChangesToModify.length, 1); assert.equal(configurationChangesToModify[0].newValue?.key, "app:Settings:FontColor"); assert.equal(configurationChangesToRefresh.length, 2); assert.equal(configurationChangesToDelete.length, 0); @@ -298,7 +298,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () }; // Use Import API with pre-calculated changes - const changesSourceForTest = new ConfigurationChangesSource(configurationChanges); + const changesSourceForTest = new ConfigurationChangesSource(configurationChanges, options.profile !== ConfigurationProfile.Default); await appConfigurationImporter.Import(changesSourceForTest, { timeout: 5, progressCallback: reportImportProgress }); assert.equal(finished, 3); assert.equal(total, 3); @@ -312,7 +312,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () { changeType: ChangeType.Create, currentValue: null, newValue: { key: "testKey", value: "testValue" } } ]; - const changesSource = new ConfigurationChangesSource(configurationChanges); + const changesSource = new ConfigurationChangesSource(configurationChanges, false); try { await appConfigurationImporter.Import(changesSource, { timeout: 5, strict: true, importMode: ImportMode.All }); @@ -349,7 +349,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () const configurationChangesToDelete = configurationChanges.filter(c => c.changeType === ChangeType.Delete); assert.equal(configurationChangesToAdd.length, 0); - assert.equal(configurationChangesToModify.length, 2); + assert.equal(configurationChangesToModify.length, 1); assert.equal(configurationChangesToModify[0].newValue?.key, "app:Settings:FontColor"); assert.ok(configurationChangesToModify[0].currentValue, "existing setting should be present for diff display"); assert.equal(configurationChangesToRefresh.length, 2); @@ -374,7 +374,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () const configurationChangesToDelete = configurationChanges.filter(c => c.changeType === ChangeType.Delete); assert.equal(configurationChangesToAdd.length, 0); - assert.equal(configurationChangesToModify.length, 2); + assert.equal(configurationChangesToModify.length, 1); assert.equal(configurationChangesToModify[0].newValue?.key, "app:Settings:FontColor"); assert.ok(configurationChangesToModify[0].currentValue, "existing setting should be present for diff display"); assert.equal(configurationChangesToRefresh.length, 0); diff --git a/libraries/azure-app-configuration-importer/tests/util.spec.ts b/libraries/azure-app-configuration-importer/tests/util.spec.ts index ea499a8..6214867 100644 --- a/libraries/azure-app-configuration-importer/tests/util.spec.ts +++ b/libraries/azure-app-configuration-importer/tests/util.spec.ts @@ -47,14 +47,16 @@ describe("Test the utility methods", () => { const testKeyValue1: SetConfigurationSettingParam = { key: "key1", value: "value1", - label: "dev", + label: "dev", + description: "description", contentType:"application/json", tags:{tag1: "tag1"} }; const testKeyValue2: ConfigurationSetting = { key: "key1", value: "value2", - label: "dev", + label: "dev", + description: "description", contentType:"application/json", tags:{tag1: "tag1"}, isReadOnly: false @@ -62,14 +64,16 @@ describe("Test the utility methods", () => { const testKeyValue3: SetConfigurationSettingParam = { key: "key2", value: "value1", - label: "prod", + label: "prod", + description: "description", contentType:"application/json", tags:{tag1: "tag1"} }; const testKeyValue4: ConfigurationSetting = { key: "key2", value: "value1", - label: "prod", + label: "prod", + description: "description", contentType:"application/json", tags:{tag1: "tag2"}, isReadOnly: false @@ -77,14 +81,16 @@ describe("Test the utility methods", () => { const testKeyValue5: SetConfigurationSettingParam = { key: "key2", value: "value1", - label: "prod", + label: "prod", + description: "description", contentType:"application/json", tags:{tag1: "tag1"} }; const testKeyValue6: ConfigurationSetting = { key: "key2", value: "value1", - label: "prod", + label: "prod", + description: "description", contentType:"application/json", tags:{tag1: "tag2"}, isReadOnly: false @@ -93,7 +99,8 @@ describe("Test the utility methods", () => { const testKeyValue7: SetConfigurationSettingParam = { key: "FeatureA", value: "{\"id\":\"Beta\",\"description\":\"Beta feature\",\"enabled\":true,\"conditions\":{\"client_filters\":[]}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} }; @@ -101,7 +108,8 @@ describe("Test the utility methods", () => { const testKeyValue8: ConfigurationSetting = { key: "FeatureB", value: "{\"id\":\"Beta\",\"description\":\"Beta feature updated description\",\"enabled\":true,\"conditions\":{\"client_filters\":[]}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: false @@ -110,38 +118,60 @@ describe("Test the utility methods", () => { const testKeyValue9: SetConfigurationSettingParam = { key: "FeatureX", value: "{\"id\":\"Beta\",\"description\":\"Beta feature updated description\",\"enabled\":true,\"conditions\":{\"client_filters\":[{\"name\": \"Percentage\",\"parameters\": {\"PercentageFilterSetting\": \"50\"}}]}}", - label: "test", + label: "test", + description: "description", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} }; const testKeyValue10: ConfigurationSetting = { key: "FeatureY", value: "{\"id\":\"Beta\",\"description\":\"Beta feature updated description\",\"enabled\":true,\"conditions\":{\"client_filters\":[{\"name\": \"Percentage\",\"parameters\": {\"PercentageFilterSetting\": \"60\"}}]}}", - label: "test", + label: "test", + description: "description", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: false }; + const testKeyValue11: SetConfigurationSettingParam = { + key: "key2", + value: "value1", + label: "prod", + description: "description", + contentType:"application/json", + tags:{tag1: "tag1"} + }; + const testKeyValue12: ConfigurationSetting = { + key: "key2", + value: "value1", + label: "prod", + description: "description updated", + contentType:"application/json", + tags:{tag1: "tag1"}, + isReadOnly: false + }; - assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2)); - assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4)); - assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6)); - assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8)); - assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10)); + assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue11, testKeyValue12, true)); }); it("Determine if key-values with similar values are equal", async()=>{ const testKeyValue1: SetConfigurationSettingParam = { key: "key1", value: "value1", - label: "dev", + label: "dev", + description: "description", contentType:"application/json" }; const testKeyValue2: ConfigurationSetting = { key: "key1", value: "value1", - label: "dev", + label: "dev", + description: "description", contentType:"application/json", isReadOnly: false }; @@ -149,14 +179,16 @@ describe("Test the utility methods", () => { const testKeyValue3: SetConfigurationSettingParam = { key: "key2", value: "", - label: "", + label: "", + description: "description", contentType:"application/json", tags:{tag1: "tag1"} }; const testKeyValue4: ConfigurationSetting = { key: "key2", value: "", - label: "", + label: "", + description: "description", contentType:"application/json", tags:{tag1: "tag1"}, isReadOnly: false @@ -164,27 +196,30 @@ describe("Test the utility methods", () => { const testKeyValue5: SetConfigurationSettingParam = { key: "key3", value: "value1", - label: "prod", + label: "prod", + description: "description", tags:{tag1: "tag1"} }; const testKeyValue6: ConfigurationSetting = { key: "key3", value: "value1", - label: "prod", + label: "prod", + description: "description", tags:{tag1: "tag1"}, isReadOnly: false }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2)); - assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4)); - assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6)); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); + assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); + assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); }); it("Determine if feature flag values with same values are equal", async()=> { const testKeyValue1: SetConfigurationSettingParam = { key: "FeatureA", value: "{\"id\":\"Beta\",\"description\":\"Beta feature\",\"enabled\":true,\"conditions\":{\"client_filters\":[]}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} }; @@ -192,7 +227,8 @@ describe("Test the utility methods", () => { const testKeyValue2: ConfigurationSetting = { key: "FeatureA", value: "{\"id\":\"Beta\",\"enabled\":true,\"description\":\"Beta feature\",\"conditions\":{}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: true @@ -201,14 +237,16 @@ describe("Test the utility methods", () => { const testKeyValue3: SetConfigurationSettingParam = { key: "FeatureX", value: "{\"id\":\"Beta\",\"description\":\"Beta feature updated description\",\"enabled\":true,\"conditions\":{\"client_filters\":[{\"name\": \"Percentage\",\"parameters\": {\"PercentageFilterSetting\": \"50\"}}]}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} }; const testKeyValue4: ConfigurationSetting = { key: "FeatureX", value: "{\"id\":\"Beta\",\"enabled\":true,\"description\":\"Beta feature updated description\",\"conditions\":{\"client_filters\":[{\"name\": \"Percentage\",\"parameters\": {\"PercentageFilterSetting\": \"50\"}}]}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: true @@ -216,7 +254,8 @@ describe("Test the utility methods", () => { const testKeyValue5: SetConfigurationSettingParam = { key: "FeatureX", - label: "test", + label: "test", + description: "", value: { id: "Beta", description: "Beta feature updated description", @@ -239,7 +278,8 @@ describe("Test the utility methods", () => { const testKeyValue6: ConfigurationSetting = { key: "FeatureX", value: "{\"id\":\"Beta\",\"enabled\":true,\"description\":\"Beta feature updated description\",\"conditions\":{\"client_filters\":[{\"name\": \"Microsoft.TimeWindow\",\"parameters\": {\"End\": \"Wed, 06 Sep 2023 21:00:00 GMT\"}}]}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: true @@ -248,6 +288,7 @@ describe("Test the utility methods", () => { const testKeyValue7: SetConfigurationSettingParam = { key: "FeatureX", label: "test", + description: "", value: { id: "time001", enabled: true, @@ -320,6 +361,7 @@ describe("Test the utility methods", () => { const testKeyValue8: ConfigurationSetting = { key: "FeatureX", label: "test", + description: "", value: "{\"id\":\"time001\",\"enabled\":true,\"description\":\"\",\"conditions\":{\"client_filters\":[]},\"allocation\":{\"percentile\":[{\"variant\":\"Off\",\"from\":0,\"to\":23},{\"variant\":\"On\",\"from\":23,\"to\":100}],\"group\":[{\"variant\":\"On\",\"groups\":[\"m1\"]},{\"variant\":\"Off\",\"groups\":[\"m2\",\"m3\"]}],\"user\":[{\"variant\":\"Off\",\"users\":[\"user1\",\"user3\"]},{\"variant\":\"On\",\"users\":[\"user2\"]}],\"seed\":\"bcngrfgnfgn\",\"default_when_enabled\":\"On\",\"default_when_disabled\":\"On\"},\"variants\":[{\"name\":\"Off\",\"configuration_value\":false},{\"name\":\"On\",\"configuration_value\":true}]}", contentType: "application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags: {tag1: "tag1"}, @@ -327,17 +369,18 @@ describe("Test the utility methods", () => { }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2)); - assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4)); - assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6)); - assert.isTrue(isConfigSettingEqual(testKeyValue7, testKeyValue8)); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); + assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); + assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); + assert.isTrue(isConfigSettingEqual(testKeyValue7, testKeyValue8, true)); }); it("Determine if feature flag values with different values are not equal", async()=> { const testKeyValue1: SetConfigurationSettingParam = { key: "FeatureA", value: "{\"id\":\"Beta\",\"description\":\"Beta feature\",\"enabled\":true,\"conditions\":{\"client_filters\":[]}}", - label: "test", + label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} }; @@ -346,6 +389,7 @@ describe("Test the utility methods", () => { key: "FeatureA", value: "{\"id\":\"Beta\",\"enabled\":true,\"description\":\"Beta feature description\",\"conditions\":{}}", label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: true @@ -355,6 +399,7 @@ describe("Test the utility methods", () => { key: "FeatureX", value: "{\"id\":\"Beta\",\"description\":\"Beta feature updated description\",\"enabled\":true,\"conditions\":{\"client_filters\":[{\"name\": \"Percentage\",\"parameters\": {\"PercentageFilterSetting\": \"40\"}}]}}", label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} }; @@ -362,6 +407,7 @@ describe("Test the utility methods", () => { key: "FeatureX", value: "{\"id\":\"Beta\",\"enabled\":true,\"description\":\"Beta feature updated description\",\"conditions\":{\"client_filters\":[{\"name\": \"Percentage\",\"parameters\": {\"PercentageFilterSetting\": \"50\"}}]}}", label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: true @@ -379,6 +425,7 @@ describe("Test the utility methods", () => { ] } }, + description: "", label: "test", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} @@ -388,6 +435,7 @@ describe("Test the utility methods", () => { key: "FeatureX", value: "{\"id\":\"Dev\",\"enabled\":true,\"description\":\"Beta feature updated description\",\"conditions\":{\"client_filters\":[{\"name\": \"Percentage\",\"parameters\": {\"PercentageFilterSetting\": \"50\"}}]}}", label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: true @@ -410,6 +458,7 @@ describe("Test the utility methods", () => { ] } }, + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"} }; @@ -418,6 +467,7 @@ describe("Test the utility methods", () => { key: "FeatureX", value: "{\"id\":\"Beta\",\"enabled\":true,\"description\":\"Beta feature updated description\",\"conditions\":{\"client_filters\":[{\"name\": \"Microsoft.TimeWindow\",\"parameters\": {\"End\": \"Wed, 06 Sep 2023 21:00:00 GMT\"}}]}}", label: "test", + description: "", contentType:"application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags:{tag1: "tag1"}, isReadOnly: true @@ -491,6 +541,7 @@ describe("Test the utility methods", () => { } ] }, + description: "", contentType: "application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags: { tag1: "tag1" } }; @@ -498,16 +549,17 @@ describe("Test the utility methods", () => { const testKeyValue10: ConfigurationSetting = { key: "FeatureX", label: "test", + description: "", value: "{\"id\":\"time001\",\"enabled\":true,\"description\":\"\",\"conditions\":{\"client_filters\":[]},\"allocation\":{\"percentile\":[{\"variant\":\"Off\",\"from\":0,\"to\":23},{\"variant\":\"On\",\"from\":23,\"to\":100}],\"group\":[{\"variant\":\"On\",\"groups\":[\"m1\"]},{\"variant\":\"Off\",\"groups\":[\"m2\",\"m3\"]}],\"user\":[{\"variant\":\"Off\",\"users\":[\"user1\",\"user3\"]},{\"variant\":\"On\",\"users\":[\"user2\"]}],\"seed\":\"bcngrfgnfgn\",\"default_when_enabled\":\"On\",\"default_when_disabled\":\"On\"},\"variants\":[{\"name\":\"Off\",\"configuration_value\":false},{\"name\":\"On\",\"configuration_value\":true,\"status_override\":\"None\"}]}", contentType: "application/vnd.microsoft.appconfig.ff+json;charset=utf-8", tags: {}, isReadOnly: true }; - assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2)); - assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4)); - assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6)); - assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8)); - assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10)); + assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, true)); }); }); From fb97bf1ec368eb35ab156af217e7a7ef098a9f50 Mon Sep 17 00:00:00 2001 From: MaryanneNjeri Date: Sun, 12 Jul 2026 12:41:38 +0300 Subject: [PATCH 3/7] Address PR comments --- .../src/settingsImport/configurationChangesSource.ts | 4 ++-- .../tests/appConfigurationImporter.spec.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts index 6f95369..8f35814 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts @@ -25,12 +25,12 @@ export class ConfigurationChangesSource implements ConfigurationSettingsSource { public supportsDescriptionField: boolean; private readonly configurationChanges: Array; - constructor(configurationChanges: Array, supportDescriptionField: boolean, filterOptions?: ListConfigurationSettingsOptions) { + constructor(configurationChanges: Array, supportDescriptionField?: boolean, filterOptions?: ListConfigurationSettingsOptions) { if (filterOptions && Object.keys(filterOptions).length > 0) { throw new ArgumentError("FilterOptions are not supported for ConfigurationChangesSource."); } - this.supportsDescriptionField = supportDescriptionField; this.configurationChanges = configurationChanges; + this.supportsDescriptionField = supportDescriptionField ?? false; } /** diff --git a/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts b/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts index aa3a6e7..a84a402 100644 --- a/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts +++ b/libraries/azure-app-configuration-importer/tests/appConfigurationImporter.spec.ts @@ -298,7 +298,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () }; // Use Import API with pre-calculated changes - const changesSourceForTest = new ConfigurationChangesSource(configurationChanges, options.profile !== ConfigurationProfile.Default); + const changesSourceForTest = new ConfigurationChangesSource(configurationChanges); await appConfigurationImporter.Import(changesSourceForTest, { timeout: 5, progressCallback: reportImportProgress }); assert.equal(finished, 3); assert.equal(total, 3); @@ -312,7 +312,7 @@ describe("Call Import API to import configuration file to AppConfiguration", () { changeType: ChangeType.Create, currentValue: null, newValue: { key: "testKey", value: "testValue" } } ]; - const changesSource = new ConfigurationChangesSource(configurationChanges, false); + const changesSource = new ConfigurationChangesSource(configurationChanges); try { await appConfigurationImporter.Import(changesSource, { timeout: 5, strict: true, importMode: ImportMode.All }); From 06898654ef627a2060b5b68d9961b6c2c9872ce6 Mon Sep 17 00:00:00 2001 From: MaryanneNjeri Date: Sun, 12 Jul 2026 13:10:25 +0300 Subject: [PATCH 4/7] Added test --- .../configurationSettingsSource.ts | 1 - ...adableStreamConfigurationSettingsSource.ts | 2 +- .../stringConfigurationSettingsSource.ts | 2 +- .../tests/util.spec.ts | 23 +++++++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts index 635ed5b..38c4235 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts @@ -23,7 +23,6 @@ export interface ConfigurationSettingsSource { /** * Description field supported in the configuration settings source * - * @returns boolean */ supportsDescriptionField: boolean; diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts index 167eef3..ee6847d 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts @@ -11,7 +11,7 @@ import { validateOptions} from "../internal/utils"; export class ReadableStreamConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportsDescriptionField: boolean = false; + public supportsDescriptionField = false; private options: SourceOptions; private data: ReadableStream | NodeJS.ReadableStream; diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts index a7065a8..ab5e733 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts @@ -24,7 +24,7 @@ import { KvSetConfigurationSettingsConverter } from "../internal/parsers/kvSetCo */ export class StringConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportsDescriptionField: boolean = false; + public supportsDescriptionField = false; private options: SourceOptions; private data: string; diff --git a/libraries/azure-app-configuration-importer/tests/util.spec.ts b/libraries/azure-app-configuration-importer/tests/util.spec.ts index 6214867..069daea 100644 --- a/libraries/azure-app-configuration-importer/tests/util.spec.ts +++ b/libraries/azure-app-configuration-importer/tests/util.spec.ts @@ -562,4 +562,27 @@ describe("Test the utility methods", () => { assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, true)); assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, true)); }); + + it("Determine the description field is ignored when supportDescriptionField is false", async()=> { + const testKeyValue1: SetConfigurationSettingParam = { + key: "key2", + value: "value1", + label: "prod", + description: "description", + contentType:"application/json", + tags:{tag1: "tag1"} + }; + + const testKeyValue2: ConfigurationSetting = { + key: "key2", + value: "value1", + label: "prod", + description: "description updated", + contentType:"application/json", + tags:{tag1: "tag1"}, + isReadOnly: false + }; + + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, false)); + }) }); From 2706ad04544c1b11abcd4ae354506ee624c41fac Mon Sep 17 00:00:00 2001 From: MaryanneNjeri Date: Sun, 12 Jul 2026 13:18:14 +0300 Subject: [PATCH 5/7] Add missing semi colon --- libraries/azure-app-configuration-importer/tests/util.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/azure-app-configuration-importer/tests/util.spec.ts b/libraries/azure-app-configuration-importer/tests/util.spec.ts index 069daea..99733e8 100644 --- a/libraries/azure-app-configuration-importer/tests/util.spec.ts +++ b/libraries/azure-app-configuration-importer/tests/util.spec.ts @@ -584,5 +584,5 @@ describe("Test the utility methods", () => { }; assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, false)); - }) + }); }); From e91512a72089384c8af20e3cbef8edfac1a7c070 Mon Sep 17 00:00:00 2001 From: MaryanneNjeri Date: Mon, 20 Jul 2026 18:58:56 +0300 Subject: [PATCH 6/7] Updated configuration settings source interface to include supportedFields property --- .../src/appConfigurationImporter.ts | 2 +- .../src/internal/utils.ts | 47 ++++++++++++++----- .../src/models.ts | 10 ++++ .../configurationChangesSource.ts | 8 ++-- .../configurationSettingsSource.ts | 6 +-- .../iterableConfigurationSettingsSource.ts | 5 +- ...adableStreamConfigurationSettingsSource.ts | 7 +-- .../stringConfigurationSettingsSource.ts | 7 +-- .../tests/util.spec.ts | 41 ++++++++-------- 9 files changed, 84 insertions(+), 49 deletions(-) diff --git a/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts b/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts index 724af56..6abfe34 100644 --- a/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts +++ b/libraries/azure-app-configuration-importer/src/appConfigurationImporter.ts @@ -161,7 +161,7 @@ export class AppConfigurationImporter { // Remove from add list since it already exists toAddKeys.delete(composite); - if (!isConfigSettingEqual(incoming, existing, configSettingsSource.supportsDescriptionField)) { + if (!isConfigSettingEqual(incoming, existing, configSettingsSource.supportedFields)) { configurationChanges.push({ changeType: ChangeType.Update, currentValue: existing, diff --git a/libraries/azure-app-configuration-importer/src/internal/utils.ts b/libraries/azure-app-configuration-importer/src/internal/utils.ts index 5e7b949..9648b7d 100644 --- a/libraries/azure-app-configuration-importer/src/internal/utils.ts +++ b/libraries/azure-app-configuration-importer/src/internal/utils.ts @@ -8,7 +8,7 @@ import { featureFlagContentType, SecretReferenceValue } from "@azure/app-configuration"; import { isEmpty, isEqual } from "lodash"; -import { Tags, FeatureFlagClientFilters } from "../models"; +import { Tags, FeatureFlagClientFilters, ConfigurationSettingsFields } from "../models"; import { SourceOptions } from "../options"; import { ConfigurationFormat, ConfigurationProfile } from "../enums"; import { ArgumentError, ArgumentNullError } from "../errors"; @@ -41,18 +41,39 @@ export function isJsonContentType(contentType?: string): boolean { } /** @internal*/ -export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting, isDescriptionFieldSupported: boolean) { - let valueIsEqual: boolean = settingA.value == settingB.value; - - if (settingA.contentType == featureFlagContentType && - settingB.contentType == featureFlagContentType && - settingA.value !== undefined && - settingB.value !== undefined) { - valueIsEqual = isFeatureFlagValueEqual(settingA.value as string | MsFeatureFlagValue, settingB.value); - } - return valueIsEqual && - settingA.contentType == settingB.contentType && - areTagsEqual(settingA.tags, settingB.tags) && (!isDescriptionFieldSupported || settingA.description == settingB.description); +export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting, supportedFields: Array): boolean { + const compareAll = supportedFields.includes(ConfigurationSettingsFields.All); + const shouldCompare = (field: ConfigurationSettingsFields): boolean => + compareAll || supportedFields.includes(field); + + if (shouldCompare(ConfigurationSettingsFields.Value)) { + let valueIsEqual: boolean = settingA.value == settingB.value; + + if (settingA.contentType == featureFlagContentType && + settingB.contentType == featureFlagContentType && + settingA.value !== undefined && + settingB.value !== undefined) { + valueIsEqual = isFeatureFlagValueEqual(settingA.value as string | MsFeatureFlagValue, settingB.value); + } + + if (!valueIsEqual) { + return false; + } + } + + if (shouldCompare(ConfigurationSettingsFields.ContentType) && settingA.contentType != settingB.contentType) { + return false; + } + + if (shouldCompare(ConfigurationSettingsFields.Tags) && !areTagsEqual(settingA.tags, settingB.tags)) { + return false; + } + + if (shouldCompare(ConfigurationSettingsFields.Description) && settingA.description != settingB.description) { + return false; + } + + return true; } /** @internal*/ diff --git a/libraries/azure-app-configuration-importer/src/models.ts b/libraries/azure-app-configuration-importer/src/models.ts index 5d106ec..454206b 100644 --- a/libraries/azure-app-configuration-importer/src/models.ts +++ b/libraries/azure-app-configuration-importer/src/models.ts @@ -59,4 +59,14 @@ export interface ConfigurationSettingChange { currentValue: ConfigurationSetting | null; /** The new value of the configuration setting */ newValue: SetConfigurationSettingParam | null; +} + +export enum ConfigurationSettingsFields { + All, + Key, + Value, + Label, + Description, + ContentType, + Tags } \ No newline at end of file diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts index 8f35814..dd598e5 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/configurationChangesSource.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { ConfigurationSettingsSource } from "./configurationSettingsSource"; -import { ConfigurationSettingChange } from "../models"; +import { ConfigurationSettingChange, ConfigurationSettingsFields } from "../models"; import { ListConfigurationSettingsOptions } from "@azure/app-configuration"; import { ArgumentError } from "../errors"; @@ -22,15 +22,15 @@ import { ArgumentError } from "../errors"; * ``` */ export class ConfigurationChangesSource implements ConfigurationSettingsSource { - public supportsDescriptionField: boolean; + public supportedFields: Array; private readonly configurationChanges: Array; - constructor(configurationChanges: Array, supportDescriptionField?: boolean, filterOptions?: ListConfigurationSettingsOptions) { + constructor(configurationChanges: Array, supportedFields?: Array, filterOptions?: ListConfigurationSettingsOptions) { if (filterOptions && Object.keys(filterOptions).length > 0) { throw new ArgumentError("FilterOptions are not supported for ConfigurationChangesSource."); } this.configurationChanges = configurationChanges; - this.supportsDescriptionField = supportDescriptionField ?? false; + this.supportedFields = supportedFields ?? [ConfigurationSettingsFields.All]; } /** diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts index 38c4235..39615a8 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts @@ -7,7 +7,7 @@ import { SecretReferenceValue, SetConfigurationSettingParam } from "@azure/app-configuration"; -import { ConfigurationSettingChange } from "../models"; +import { ConfigurationSettingChange, ConfigurationSettingsFields } from "../models"; /** * Interface of all ConfigurationSettingsSource @@ -21,10 +21,10 @@ export interface ConfigurationSettingsSource { GetConfigurationSettings(): Promise> | Array>; /** - * Description field supported in the configuration settings source + * Fields supported in the configuration settings source * */ - supportsDescriptionField: boolean; + supportedFields: ConfigurationSettingsFields[]; /** * Get label and prefix filter diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts index 11a2dfe..6977621 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts @@ -15,17 +15,18 @@ import { secretReferenceContentType} from "@azure/app-configuration"; import { IterableSourceOptions } from "../options"; import { ArgumentError } from "../errors"; +import { ConfigurationSettingsFields } from "../models"; export class IterableConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportsDescriptionField: boolean; + public supportedFields: Array; private data: PagedAsyncIterableIterator, ListConfigurationSettingPage, PageSettings>; private options: IterableSourceOptions; constructor(options: IterableSourceOptions) { this.data = options.data; this.options = options; - this.supportsDescriptionField = true; + this.supportedFields = [ConfigurationSettingsFields.All]; this.FilterOptions = { keyFilter: options.prefix ? options.prefix + "*" : undefined, diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts index ee6847d..9c8ca63 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts @@ -8,10 +8,11 @@ import { ConfigurationSettingsSource } from "./configurationSettingsSource"; import { ConfigurationProfile } from "../enums"; import { StringConfigurationSettingsSource } from "./stringConfigurationSettingsSource"; import { validateOptions} from "../internal/utils"; +import { ConfigurationSettingsFields } from "../models"; export class ReadableStreamConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportsDescriptionField = false; + public supportedFields = [ConfigurationSettingsFields.All]; private options: SourceOptions; private data: ReadableStream | NodeJS.ReadableStream; @@ -25,14 +26,14 @@ export class ReadableStreamConfigurationSettingsSource implements ConfigurationS keyFilter: options.prefix ? options.prefix + "*" : undefined, labelFilter: options.label ? options.label : "\0" }; - this.supportsDescriptionField = false; + this.supportedFields = [ConfigurationSettingsFields.Key, ConfigurationSettingsFields.Label, ConfigurationSettingsFields.Value, ConfigurationSettingsFields.ContentType, ConfigurationSettingsFields.Tags]; } else if (options.profile == ConfigurationProfile.KvSet) { this.FilterOptions = { keyFilter: "*", labelFilter: "*" }; - this.supportsDescriptionField = true; + this.supportedFields = [ConfigurationSettingsFields.All]; } } diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts index ab5e733..9f11645 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts @@ -18,13 +18,14 @@ import { validateOptions } from "../internal/utils"; import { ConfigurationSettingsConverter } from "../internal/parsers/configurationSettingsConverter"; import { DefaultConfigurationSettingsConverter } from "../internal/parsers/defaultConfigurationSettingsConverter"; import { KvSetConfigurationSettingsConverter } from "../internal/parsers/kvSetConfigurationSettingsConverter"; +import { ConfigurationSettingsFields } from "../models"; /** * ConfigurationSettingsSource implementation of string data configuration source */ export class StringConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportsDescriptionField = false; + public supportedFields: Array = [ConfigurationSettingsFields.All]; private options: SourceOptions; private data: string; @@ -39,14 +40,14 @@ export class StringConfigurationSettingsSource implements ConfigurationSettingsS labelFilter: options.label ? options.label : "\0" }; - this.supportsDescriptionField = false; + this.supportedFields = [ConfigurationSettingsFields.Key, ConfigurationSettingsFields.Label, ConfigurationSettingsFields.Value, ConfigurationSettingsFields.ContentType, ConfigurationSettingsFields.Tags]; } else if (options.profile == ConfigurationProfile.KvSet) { this.FilterOptions = { keyFilter: "*", labelFilter: "*" }; - this.supportsDescriptionField = true; + this.supportedFields = [ConfigurationSettingsFields.All]; } } diff --git a/libraries/azure-app-configuration-importer/tests/util.spec.ts b/libraries/azure-app-configuration-importer/tests/util.spec.ts index 99733e8..bde6dde 100644 --- a/libraries/azure-app-configuration-importer/tests/util.spec.ts +++ b/libraries/azure-app-configuration-importer/tests/util.spec.ts @@ -5,6 +5,7 @@ import { assert } from "chai"; import { areTagsEqual, isJsonContentType, isConfigSettingEqual } from "../src/internal/utils"; import { ConfigurationSetting, FeatureFlagValue, SetConfigurationSettingParam } from "@azure/app-configuration"; import { MsFeatureFlagValue } from "../src/featureFlag"; +import { ConfigurationSettingsFields } from "../src/models"; describe("Test the utility methods", () => { it("Determine the content type is json contentType", async () => { @@ -150,12 +151,12 @@ describe("Test the utility methods", () => { isReadOnly: false }; - assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue11, testKeyValue12, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue11, testKeyValue12, [ConfigurationSettingsFields.All])); }); it("Determine if key-values with similar values are equal", async()=>{ @@ -209,9 +210,9 @@ describe("Test the utility methods", () => { isReadOnly: false }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); - assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); - assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); + assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); + assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); }); it("Determine if feature flag values with same values are equal", async()=> { @@ -369,10 +370,10 @@ describe("Test the utility methods", () => { }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); - assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); - assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); - assert.isTrue(isConfigSettingEqual(testKeyValue7, testKeyValue8, true)); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); + assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); + assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); + assert.isTrue(isConfigSettingEqual(testKeyValue7, testKeyValue8, [ConfigurationSettingsFields.All])); }); it("Determine if feature flag values with different values are not equal", async()=> { @@ -556,14 +557,14 @@ describe("Test the utility methods", () => { isReadOnly: true }; - assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, true)); - assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, true)); + assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, [ConfigurationSettingsFields.All])); }); - it("Determine the description field is ignored when supportDescriptionField is false", async()=> { + it("Determine the description field is ignored when its not included in the supported fields", async()=> { const testKeyValue1: SetConfigurationSettingParam = { key: "key2", value: "value1", @@ -583,6 +584,6 @@ describe("Test the utility methods", () => { isReadOnly: false }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, false)); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.Key, ConfigurationSettingsFields.Label, ConfigurationSettingsFields.Value, ConfigurationSettingsFields.ContentType, ConfigurationSettingsFields.Tags])); }); }); From e46491a2f61699bae22be83821b38e421c9542da Mon Sep 17 00:00:00 2001 From: MaryanneNjeri Date: Tue, 21 Jul 2026 12:50:01 +0300 Subject: [PATCH 7/7] Address PR comment --- .../src/internal/utils.ts | 15 +++----- .../src/models.ts | 16 ++++---- .../configurationChangesSource.ts | 6 +-- .../configurationSettingsSource.ts | 2 +- .../iterableConfigurationSettingsSource.ts | 4 +- ...adableStreamConfigurationSettingsSource.ts | 6 +-- .../stringConfigurationSettingsSource.ts | 6 +-- .../tests/util.spec.ts | 38 +++++++++---------- 8 files changed, 46 insertions(+), 47 deletions(-) diff --git a/libraries/azure-app-configuration-importer/src/internal/utils.ts b/libraries/azure-app-configuration-importer/src/internal/utils.ts index 9648b7d..22ab484 100644 --- a/libraries/azure-app-configuration-importer/src/internal/utils.ts +++ b/libraries/azure-app-configuration-importer/src/internal/utils.ts @@ -41,12 +41,9 @@ export function isJsonContentType(contentType?: string): boolean { } /** @internal*/ -export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting, supportedFields: Array): boolean { - const compareAll = supportedFields.includes(ConfigurationSettingsFields.All); - const shouldCompare = (field: ConfigurationSettingsFields): boolean => - compareAll || supportedFields.includes(field); - - if (shouldCompare(ConfigurationSettingsFields.Value)) { +export function isConfigSettingEqual(settingA: SetConfigurationSettingParam, settingB: ConfigurationSetting, supportedFields: ConfigurationSettingsFields): boolean { + + if ((supportedFields & ConfigurationSettingsFields.Value) === ConfigurationSettingsFields.Value) { let valueIsEqual: boolean = settingA.value == settingB.value; if (settingA.contentType == featureFlagContentType && @@ -61,15 +58,15 @@ export function isConfigSettingEqual(settingA: SetConfigurationSettingParam; + public supportedFields: ConfigurationSettingsFields; private readonly configurationChanges: Array; - constructor(configurationChanges: Array, supportedFields?: Array, filterOptions?: ListConfigurationSettingsOptions) { + constructor(configurationChanges: Array, supportedFields?: ConfigurationSettingsFields, filterOptions?: ListConfigurationSettingsOptions) { if (filterOptions && Object.keys(filterOptions).length > 0) { throw new ArgumentError("FilterOptions are not supported for ConfigurationChangesSource."); } this.configurationChanges = configurationChanges; - this.supportedFields = supportedFields ?? [ConfigurationSettingsFields.All]; + this.supportedFields = supportedFields ?? ConfigurationSettingsFields.All; } /** diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts index 39615a8..ada229a 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/configurationSettingsSource.ts @@ -24,7 +24,7 @@ export interface ConfigurationSettingsSource { * Fields supported in the configuration settings source * */ - supportedFields: ConfigurationSettingsFields[]; + supportedFields: ConfigurationSettingsFields; /** * Get label and prefix filter diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts index 6977621..889b02c 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/iterableConfigurationSettingsSource.ts @@ -19,14 +19,14 @@ import { ConfigurationSettingsFields } from "../models"; export class IterableConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportedFields: Array; + public supportedFields: ConfigurationSettingsFields; private data: PagedAsyncIterableIterator, ListConfigurationSettingPage, PageSettings>; private options: IterableSourceOptions; constructor(options: IterableSourceOptions) { this.data = options.data; this.options = options; - this.supportedFields = [ConfigurationSettingsFields.All]; + this.supportedFields = ConfigurationSettingsFields.All; this.FilterOptions = { keyFilter: options.prefix ? options.prefix + "*" : undefined, diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts index 9c8ca63..4ba69a4 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/readableStreamConfigurationSettingsSource.ts @@ -12,7 +12,7 @@ import { ConfigurationSettingsFields } from "../models"; export class ReadableStreamConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportedFields = [ConfigurationSettingsFields.All]; + public supportedFields = ConfigurationSettingsFields.All; private options: SourceOptions; private data: ReadableStream | NodeJS.ReadableStream; @@ -26,14 +26,14 @@ export class ReadableStreamConfigurationSettingsSource implements ConfigurationS keyFilter: options.prefix ? options.prefix + "*" : undefined, labelFilter: options.label ? options.label : "\0" }; - this.supportedFields = [ConfigurationSettingsFields.Key, ConfigurationSettingsFields.Label, ConfigurationSettingsFields.Value, ConfigurationSettingsFields.ContentType, ConfigurationSettingsFields.Tags]; + this.supportedFields = ConfigurationSettingsFields.Key | ConfigurationSettingsFields.Label | ConfigurationSettingsFields.Value | ConfigurationSettingsFields.ContentType | ConfigurationSettingsFields.Tags; } else if (options.profile == ConfigurationProfile.KvSet) { this.FilterOptions = { keyFilter: "*", labelFilter: "*" }; - this.supportedFields = [ConfigurationSettingsFields.All]; + this.supportedFields = ConfigurationSettingsFields.All; } } diff --git a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts index 9f11645..b6978c3 100644 --- a/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts +++ b/libraries/azure-app-configuration-importer/src/settingsImport/stringConfigurationSettingsSource.ts @@ -25,7 +25,7 @@ import { ConfigurationSettingsFields } from "../models"; */ export class StringConfigurationSettingsSource implements ConfigurationSettingsSource { public FilterOptions: ListConfigurationSettingsOptions = {}; - public supportedFields: Array = [ConfigurationSettingsFields.All]; + public supportedFields: ConfigurationSettingsFields = ConfigurationSettingsFields.All; private options: SourceOptions; private data: string; @@ -40,14 +40,14 @@ export class StringConfigurationSettingsSource implements ConfigurationSettingsS labelFilter: options.label ? options.label : "\0" }; - this.supportedFields = [ConfigurationSettingsFields.Key, ConfigurationSettingsFields.Label, ConfigurationSettingsFields.Value, ConfigurationSettingsFields.ContentType, ConfigurationSettingsFields.Tags]; + this.supportedFields = ConfigurationSettingsFields.Key | ConfigurationSettingsFields.Label | ConfigurationSettingsFields.Value | ConfigurationSettingsFields.ContentType| ConfigurationSettingsFields.Tags; } else if (options.profile == ConfigurationProfile.KvSet) { this.FilterOptions = { keyFilter: "*", labelFilter: "*" }; - this.supportedFields = [ConfigurationSettingsFields.All]; + this.supportedFields = ConfigurationSettingsFields.All; } } diff --git a/libraries/azure-app-configuration-importer/tests/util.spec.ts b/libraries/azure-app-configuration-importer/tests/util.spec.ts index bde6dde..7931da1 100644 --- a/libraries/azure-app-configuration-importer/tests/util.spec.ts +++ b/libraries/azure-app-configuration-importer/tests/util.spec.ts @@ -151,12 +151,12 @@ describe("Test the utility methods", () => { isReadOnly: false }; - assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue11, testKeyValue12, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue11, testKeyValue12, ConfigurationSettingsFields.All)); }); it("Determine if key-values with similar values are equal", async()=>{ @@ -210,9 +210,9 @@ describe("Test the utility methods", () => { isReadOnly: false }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); - assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); - assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, ConfigurationSettingsFields.All)); + assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, ConfigurationSettingsFields.All)); + assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, ConfigurationSettingsFields.All)); }); it("Determine if feature flag values with same values are equal", async()=> { @@ -370,10 +370,10 @@ describe("Test the utility methods", () => { }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); - assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); - assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); - assert.isTrue(isConfigSettingEqual(testKeyValue7, testKeyValue8, [ConfigurationSettingsFields.All])); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, ConfigurationSettingsFields.All)); + assert.isTrue(isConfigSettingEqual(testKeyValue3, testKeyValue4, ConfigurationSettingsFields.All)); + assert.isTrue(isConfigSettingEqual(testKeyValue5, testKeyValue6, ConfigurationSettingsFields.All)); + assert.isTrue(isConfigSettingEqual(testKeyValue7, testKeyValue8, ConfigurationSettingsFields.All)); }); it("Determine if feature flag values with different values are not equal", async()=> { @@ -557,11 +557,11 @@ describe("Test the utility methods", () => { isReadOnly: true }; - assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, [ConfigurationSettingsFields.All])); - assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, [ConfigurationSettingsFields.All])); + assert.isFalse(isConfigSettingEqual(testKeyValue1, testKeyValue2, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue3, testKeyValue4, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue5, testKeyValue6, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue7, testKeyValue8, ConfigurationSettingsFields.All)); + assert.isFalse(isConfigSettingEqual(testKeyValue9, testKeyValue10, ConfigurationSettingsFields.All)); }); it("Determine the description field is ignored when its not included in the supported fields", async()=> { @@ -584,6 +584,6 @@ describe("Test the utility methods", () => { isReadOnly: false }; - assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, [ConfigurationSettingsFields.Key, ConfigurationSettingsFields.Label, ConfigurationSettingsFields.Value, ConfigurationSettingsFields.ContentType, ConfigurationSettingsFields.Tags])); + assert.isTrue(isConfigSettingEqual(testKeyValue1, testKeyValue2, ConfigurationSettingsFields.Key| ConfigurationSettingsFields.Label| ConfigurationSettingsFields.Value| ConfigurationSettingsFields.ContentType| ConfigurationSettingsFields.Tags)); }); });