packages/config: keep track of key prefix to display better error messages

This commit is contained in:
Patrik Oldsberg
2020-06-17 17:54:11 +02:00
parent 5294d71fe9
commit 625a50989d
2 changed files with 26 additions and 10 deletions
+4 -1
View File
@@ -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();
+22 -9
View File
@@ -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<T extends JsonValue>(
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),
);
}
}