Fixes #3659
This commit is contained in:
Josh Gummersall 2021-05-06 14:45:01 -07:00 коммит произвёл GitHub
Родитель af9a8b39cb
Коммит 77d8fb7893
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 48 добавлений и 12 удалений

Просмотреть файл

@ -1,5 +1,6 @@
{
"luis": {
"fancySetting": "fancyValue"
"fancySetting": "fancyValue",
"override": "new value"
}
}

Просмотреть файл

@ -40,12 +40,12 @@
"botbuilder-dialogs-declarative": "4.1.6",
"botframework-connector": "4.1.6",
"dependency-graph": "^0.10.0",
"nconf": "^0.11.2",
"nconf": "0.11.2",
"runtypes": "~6.3.0",
"yargs-parser": "^20.2.7"
},
"devDependencies": {
"@types/nconf": "^0.10.0",
"@types/nconf": "0.10.0",
"mocha": "^8.2.1",
"nyc": "^15.1.0"
},

Просмотреть файл

@ -91,10 +91,38 @@ export class Configuration implements CoreConfiguration {
* Load a file as a configuration source.
*
* @param name file name
* @param override optional flag that ensures this file takes precedence over other files
* @returns this for chaining
*/
file(name: string): this {
file(name: string, override = false): this {
this.provider.file(name, name);
// If we are given a key to override, we need to reach into the nconf provider and rearrange things.
// The nconf provider maintains an object that maps names to stores. When looking up a key, nconf iterates
// through the stores in insertion order and returns the first value it finds. This is not ideal because,
// in order to rearrange stores, we have to essentially reconstruct the object so the insertion order is
// correct. So this code does that.
if (override) {
// Construct list of entries in current insertion order
const stores = this.provider.stores ?? {};
const entries = Object.entries<Record<string, string>>(stores);
// Locate store to override, if it exists
const index = entries.findIndex(([, store]) => store.type === 'file');
// If store exists, we need to remove the store we just added, splice it into entries, and then reduce
// it back into an object.
if (index !== -1) {
// insert this store before the store to override
entries.splice(index, 0, [name, stores[name]]);
// slice this store from end of list, then reduce back into object
this.provider.stores = entries
.slice(0, entries.length - 1)
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
}
}
return this;
}

Просмотреть файл

@ -353,6 +353,7 @@ async function addSettingsBotComponents(services: ServiceCollection, configurati
}
}
// Note: any generated files take precedence over `appsettings.json`.
function addComposerConfiguration(configuration: Configuration): void {
const botRoot = configuration.string(['bot']) ?? '.';
configuration.set(['BotRoot'], botRoot);
@ -374,12 +375,12 @@ function addComposerConfiguration(configuration: Configuration): void {
environment = userName;
}
configuration.file(path.join(botRoot, 'generated', `luis.settings.${environment}.${luisRegion}.json`));
configuration.file(path.join(botRoot, 'generated', `luis.settings.${environment}.${luisRegion}.json`), true);
const qnaRegion = configuration.string(['qna', 'qnaRegion']) ?? 'westus';
configuration.file(path.join(botRoot, 'generated', `qnamaker.settings.${environment}.${qnaRegion}.json`));
configuration.file(path.join(botRoot, 'generated', `qnamaker.settings.${environment}.${qnaRegion}.json`), true);
configuration.file(path.join(botRoot, 'generated', `orchestrator.settings.json`));
configuration.file(path.join(botRoot, 'generated', `orchestrator.settings.json`), true);
}
async function normalizeConfiguration(configuration: Configuration, applicationRoot: string): Promise<void> {
@ -461,11 +462,13 @@ export async function getRuntimeServices(
}
files.forEach((file) => configuration.file(path.join(configurationOrSettingsDirectory, file)));
} else {
configuration = configurationOrSettingsDirectory;
}
await normalizeConfiguration(configuration, applicationRoot);
} else {
configuration = configurationOrSettingsDirectory;
await normalizeConfiguration(configuration, applicationRoot);
}
const services = new ServiceCollection({
customAdapters: new Map(),

Просмотреть файл

@ -1,5 +1,6 @@
{
"luis": {
"environment": "mocha"
"environment": "mocha",
"override": "old value"
}
}

Просмотреть файл

@ -33,6 +33,9 @@ describe('getRuntimeServices', function () {
// Ensure that a setting in a generated file is merged in
strictEqual(configuration.string(['luis', 'fancySetting']), 'fancyValue');
// Ensure that a setting in a generated file takes precedence over appsettings
strictEqual(configuration.string(['luis', 'override']), 'new value');
});
it('supports bot components and late binding configuration', async function () {

Просмотреть файл

@ -1619,7 +1619,7 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44"
integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ==
"@types/nconf@^0.10.0":
"@types/nconf@0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@types/nconf/-/nconf-0.10.0.tgz#a5c9753a09c59d44c8e6dc94b57d73f70eb12ebe"
integrity sha512-Qh0/DWkz7fQm5h+IPFBIO5ixaFdv86V6gpbA8TPA1hhgXYtzGviv9yriqN1B+KTtmLweemKZD5XxY1cTAQPNMg==
@ -8947,7 +8947,7 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
nconf@^0.11.2:
nconf@0.11.2:
version "0.11.2"
resolved "https://registry.yarnpkg.com/nconf/-/nconf-0.11.2.tgz#707fa9db383e85ad7e8f1a17be1b053d1bd751c4"
integrity sha512-gDmn0Fgt0U0esRE8OCF72tO8AA9dtlG9eZhW4/Ex5hozNC2/LgdhWO4vKLGHNfTxcvsv6Aoxk/ROVYJD2SAdyg==