diff --git a/packages/config/src/reader.test.ts b/packages/config/src/reader.test.ts index f7804d5d49..2e61a34512 100644 --- a/packages/config/src/reader.test.ts +++ b/packages/config/src/reader.test.ts @@ -118,6 +118,8 @@ describe('ConfigReader', () => { expect(config.getOptionalString('X-x2')).toBeUndefined(); expect(config.getOptionalString('x0_x0')).toBeUndefined(); expect(config.getOptionalString('x_x-x_x')).toBeUndefined(); + + expect(new ConfigReader(undefined).getOptionalString('x')).toBeUndefined(); }); it('should throw on invalid keys', () => { @@ -138,6 +140,10 @@ describe('ConfigReader', () => { expect(() => config.getString('a.a.a.a.')).toThrow(/^Invalid config key/); expect(() => config.getString('a._')).toThrow(/^Invalid config key/); expect(() => config.getString('a.-.a')).toThrow(/^Invalid config key/); + + expect(() => new ConfigReader(undefined).getString('.')).toThrow( + /^Invalid config key/, + ); }); it('should read valid values', () => { diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts index ff7c8be6e5..f1ed8a4f3d 100644 --- a/packages/config/src/reader.ts +++ b/packages/config/src/reader.ts @@ -40,11 +40,9 @@ function typeOf(value: JsonValue | undefined): string { } export class ConfigReader implements Config { - private static readonly nullReader = new ConfigReader({}); - static fromConfigs(configs: AppConfig[]): ConfigReader { if (configs.length === 0) { - return new ConfigReader({}); + return new ConfigReader(undefined); } // Merge together all configs info a single config with recursive fallback @@ -55,13 +53,14 @@ export class ConfigReader implements Config { } constructor( - private readonly data: JsonObject, + private readonly data: JsonObject | undefined, private readonly fallback?: ConfigReader, ) {} getConfig(key: string): ConfigReader { const value = this.readValue(key); const fallbackConfig = this.fallback?.getConfig(key); + if (isObject(value)) { return new ConfigReader(value, fallbackConfig); } @@ -72,7 +71,7 @@ export class ConfigReader implements Config { )}, wanted object`, ); } - return fallbackConfig ?? ConfigReader.nullReader; + return fallbackConfig ?? new ConfigReader(undefined, undefined); } getConfigArray(key: string): ConfigReader[] { @@ -191,12 +190,18 @@ export class ConfigReader implements Config { private readValue(key: string): JsonValue | undefined { const parts = key.split('.'); - - let value: JsonValue | undefined = this.data; for (const part of parts) { if (!CONFIG_KEY_PART_PATTERN.test(part)) { throw new TypeError(`Invalid config key '${key}'`); } + } + + if (this.data === undefined) { + return undefined; + } + + let value: JsonValue | undefined = this.data; + for (const part of parts) { if (isObject(value)) { value = value[part]; } else {