From 265be1d6a1f5f34bc09d86f83a9c9f126371c0b4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 3 Sep 2020 16:35:16 +0200 Subject: [PATCH] config: try to coerce string values into numbers --- packages/config-loader/src/loader.test.ts | 21 --------------------- packages/config/src/reader.test.ts | 2 +- packages/config/src/reader.ts | 19 +++++++++++++++++-- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/packages/config-loader/src/loader.test.ts b/packages/config-loader/src/loader.test.ts index 5246722538..4a7c9f238c 100644 --- a/packages/config-loader/src/loader.test.ts +++ b/packages/config-loader/src/loader.test.ts @@ -145,25 +145,4 @@ describe('loadConfig', () => { }, ]); }); - - it('coerces port to a number', async () => { - await expect( - loadConfig({ - rootPaths: ['/secret-port'], - env: 'production', - shouldReadSecrets: true, - }), - ).resolves.toEqual([ - { - context: 'app-config.yaml', - data: { - backend: { - listen: { - port: 12345, - }, - }, - }, - }, - ]); - }); }); diff --git a/packages/config/src/reader.test.ts b/packages/config/src/reader.test.ts index 48253dcebe..3fe74aa637 100644 --- a/packages/config/src/reader.test.ts +++ b/packages/config/src/reader.test.ts @@ -88,7 +88,7 @@ function expectInvalidValues(config: ConfigReader) { "Invalid type in config for key 'string' in 'ctx', got string, wanted boolean", ); expect(() => config.getNumber('string')).toThrow( - "Invalid type in config for key 'string' in 'ctx', got string, wanted number", + "Unable to convert config value for key 'string' in 'ctx' to a number", ); expect(() => config.getString('one')).toThrow( "Invalid type in config for key 'one' in 'ctx', got number, wanted string", diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts index 65143bbd95..eb8c91e366 100644 --- a/packages/config/src/reader.ts +++ b/packages/config/src/reader.ts @@ -49,6 +49,9 @@ const errors = { missing(key: string) { return `Missing required config value at '${key}'`; }, + convert(key: string, context: string, expected: string) { + return `Unable to convert config value for key '${key}' in '${context}' to a ${expected}`; + }, }; export class ConfigReader implements Config { @@ -183,10 +186,22 @@ export class ConfigReader implements Config { } getOptionalNumber(key: string): number | undefined { - return this.readConfigValue( + const value = this.readConfigValue( key, - value => typeof value === 'number' || { expected: 'number' }, + val => + typeof val === 'number' || + typeof val === 'string' || { expected: 'number' }, ); + if (typeof value === 'number' || value === undefined) { + return value; + } + const number = Number(value); + if (!Number.isFinite(number)) { + throw new Error( + errors.convert(this.fullKey(key), this.context, 'number'), + ); + } + return number; } getBoolean(key: string): boolean {