Skip to content

Commit

Permalink
fix: configuration key handling (#3855)
Browse files Browse the repository at this point in the history
* fix: configuration key handling

Also adds some tests to ensure future consistency.

* unique values for assertions

Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com>

* clarify comment

* fix prettier issue

Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com>
  • Loading branch information
Josh Gummersall and mdrichardson authored Jul 8, 2021
1 parent cc4fe2d commit c0897ee
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,24 @@ import { Provider } from 'nconf';
/**
* Configuration implements the [IConfiguration](xref:botbuilder-dialogs-adaptive-runtime-core.IConfiguration)
* interface and adds helper methods for setting values, layering sources, and getting type checked values.
*
* @internal
*/
export class Configuration implements CoreConfiguration {
private prefix: string[] = [];
private provider = new Provider().use('memory');

/**
* Create a configuration instance
*
* @param initialValues Optional set of default values to provide
*/
constructor(initialValues?: Record<string, unknown>) {
if (initialValues) {
Object.entries(initialValues).forEach(([key, value]) => this.provider.set(key, value));
}
}

/**
* Bind a path to a Configuration instance such that calls to get or set will
* automatically include the bound path as a prefix.
Expand Down Expand Up @@ -41,7 +54,9 @@ export class Configuration implements CoreConfiguration {
* @returns the value, or undefined
*/
get<T = unknown>(path: string[] = []): T | undefined {
return this.provider.get(this.key(path));
// Note: `|| undefined` ensures that empty string is coerced to undefined
// which ensures nconf returns the entire merged configuration.
return this.provider.get(this.key(path) || undefined);
}

/**
Expand All @@ -51,6 +66,10 @@ export class Configuration implements CoreConfiguration {
* @param value value to set
*/
set(path: string[], value: unknown): void {
if (!path.length) {
throw new Error('`path` must be non-empty');
}

this.provider.set(this.key(path), value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,53 @@ describe('Configuration', function () {
assert.strictEqual(layered.get(['root', 'key']), 'layer');
});
});

describe('keys', function () {
const configuration = new Configuration({
key: 'value',
one: {
key: 'value-one',
two: {
key: 'value-two',
},
},
});

describe('non-prefixed', function () {
it('yields a value for a key', function () {
assert.strictEqual(configuration.get(['key']), 'value');
assert.strictEqual(configuration.get(['one', 'key']), 'value-one');
});

it('yields all values for a key', function () {
assert.deepStrictEqual(configuration.get(['one']), { key: 'value-one', two: { key: 'value-two' } });
});

it('yields all values for no key', function () {
assert.deepStrictEqual(configuration.get(), {
key: 'value',
one: { key: 'value-one', two: { key: 'value-two' } },
});
});
});

describe('prefixed', function () {
it('yields a value for a key', function () {
assert.strictEqual(configuration.bind(['one']).get(['key']), 'value-one');
});

it('yields all values for a key', function () {
assert.deepStrictEqual(configuration.bind(['one']).get(['two']), {
key: 'value-two',
});
});

it('yields all values for no key', function () {
assert.deepStrictEqual(configuration.bind(['one']).get(), {
key: 'value-one',
two: { key: 'value-two' },
});
});
});
});
});

0 comments on commit c0897ee

Please sign in to comment.