From 625a50989d253eeb9417efac6082d59482281560 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 17 Jun 2020 17:54:11 +0200 Subject: [PATCH] packages/config: keep track of key prefix to display better error messages --- packages/config/src/reader.test.ts | 5 ++++- packages/config/src/reader.ts | 31 +++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/config/src/reader.test.ts b/packages/config/src/reader.test.ts index 2e61a34512..f23fad8d3b 100644 --- a/packages/config/src/reader.test.ts +++ b/packages/config/src/reader.test.ts @@ -231,6 +231,9 @@ describe('ConfigReader with fallback', () => { 'a', 'b', ]); + expect(() => config.getConfig('merged').getStringArray('x')).toThrow( + 'Invalid type in config for key merged.x, got string, wanted string-array', + ); // Config arrays aren't merged either expect(config.getConfigArray('merged.configs').length).toBe(1); @@ -238,7 +241,7 @@ describe('ConfigReader with fallback', () => { expect(config.getConfigArray('merged.configs')[0].getString('a')).toBe('a'); expect(() => config.getConfigArray('merged.configs')[0].getString('missing'), - ).toThrow("Missing required config value at 'missing'"); + ).toThrow("Missing required config value at 'merged.configs[0].missing'"); expect( config.getConfigArray('merged.configs')[0].getOptionalString('b'), ).toBeUndefined(); diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts index 2c2b560536..e3c349768b 100644 --- a/packages/config/src/reader.ts +++ b/packages/config/src/reader.ts @@ -65,19 +65,23 @@ export class ConfigReader implements Config { constructor( private readonly data: JsonObject | undefined, private readonly fallback?: ConfigReader, + private readonly prefix: string = '', ) {} getConfig(key: string): ConfigReader { const value = this.readValue(key); const fallbackConfig = this.fallback?.getConfig(key); + const prefix = this.fullKey(key); if (isObject(value)) { - return new ConfigReader(value, fallbackConfig); + return new ConfigReader(value, fallbackConfig, prefix); } if (value !== undefined) { - throw new TypeError(errors.type(key, typeOf(value), 'object')); + throw new TypeError( + errors.type(this.fullKey(key), typeOf(value), 'object'), + ); } - return fallbackConfig ?? new ConfigReader(undefined, undefined); + return fallbackConfig ?? new ConfigReader(undefined, undefined, prefix); } getConfigArray(key: string): ConfigReader[] { @@ -94,13 +98,16 @@ export class ConfigReader implements Config { return true; }); - return (configs ?? []).map(obj => new ConfigReader(obj)); + return (configs ?? []).map( + (obj, index) => + new ConfigReader(obj, undefined, this.fullKey(`${key}[${index}]`)), + ); } getNumber(key: string): number { const value = this.getOptionalNumber(key); if (value === undefined) { - throw new Error(errors.missing(key)); + throw new Error(errors.missing(this.fullKey(key))); } return value; } @@ -115,7 +122,7 @@ export class ConfigReader implements Config { getBoolean(key: string): boolean { const value = this.getOptionalBoolean(key); if (value === undefined) { - throw new Error(errors.missing(key)); + throw new Error(errors.missing(this.fullKey(key))); } return value; } @@ -130,7 +137,7 @@ export class ConfigReader implements Config { getString(key: string): string { const value = this.getOptionalString(key); if (value === undefined) { - throw new Error(errors.missing(key)); + throw new Error(errors.missing(this.fullKey(key))); } return value; } @@ -146,7 +153,7 @@ export class ConfigReader implements Config { getStringArray(key: string): string[] { const value = this.getOptionalStringArray(key); if (value === undefined) { - throw new Error(errors.missing(key)); + throw new Error(errors.missing(this.fullKey(key))); } return value; } @@ -165,6 +172,10 @@ export class ConfigReader implements Config { }); } + private fullKey(key: string): string { + return `${this.prefix}${this.prefix ? '.' : ''}${key}`; + } + private readConfigValue( key: string, validate: ( @@ -184,7 +195,9 @@ export class ConfigReader implements Config { value: theValue = value, expected, } = result; - throw new TypeError(errors.type(keyName, typeOf(theValue), expected)); + throw new TypeError( + errors.type(this.fullKey(keyName), typeOf(theValue), expected), + ); } }