From dd2b9c70550554e34d3346b6bb007c5d9be97fb0 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Thu, 28 Dec 2023 12:36:30 -0800 Subject: [PATCH] Add numberSelector utility (#1126) --- .changeset/forty-stingrays-lay.md | 5 +++ .../src/booleanSelector.spec.ts | 3 +- .../src/booleanSelector.ts | 5 +-- packages/util-config-provider/src/index.ts | 2 ++ .../src/numberSelector.spec.ts | 32 +++++++++++++++++++ .../src/numberSelector.ts | 19 +++++++++++ packages/util-config-provider/src/types.ts | 4 +++ 7 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 .changeset/forty-stingrays-lay.md create mode 100644 packages/util-config-provider/src/numberSelector.spec.ts create mode 100644 packages/util-config-provider/src/numberSelector.ts create mode 100644 packages/util-config-provider/src/types.ts diff --git a/.changeset/forty-stingrays-lay.md b/.changeset/forty-stingrays-lay.md new file mode 100644 index 00000000000..90eb7b62353 --- /dev/null +++ b/.changeset/forty-stingrays-lay.md @@ -0,0 +1,5 @@ +--- +"@smithy/util-config-provider": minor +--- + +Add numberSelector utility diff --git a/packages/util-config-provider/src/booleanSelector.spec.ts b/packages/util-config-provider/src/booleanSelector.spec.ts index e2b264a7473..1632e65de76 100644 --- a/packages/util-config-provider/src/booleanSelector.spec.ts +++ b/packages/util-config-provider/src/booleanSelector.spec.ts @@ -1,4 +1,5 @@ -import { booleanSelector, SelectorType } from "./booleanSelector"; +import { booleanSelector } from "./booleanSelector"; +import { SelectorType } from "./types"; describe(booleanSelector.name, () => { const key = "key"; diff --git a/packages/util-config-provider/src/booleanSelector.ts b/packages/util-config-provider/src/booleanSelector.ts index d8e16343d0e..056044fa005 100644 --- a/packages/util-config-provider/src/booleanSelector.ts +++ b/packages/util-config-provider/src/booleanSelector.ts @@ -1,7 +1,4 @@ -export enum SelectorType { - ENV = "env", - CONFIG = "shared config entry", -} +import { SelectorType } from "./types"; /** * Returns boolean value true/false for string value "true"/"false", diff --git a/packages/util-config-provider/src/index.ts b/packages/util-config-provider/src/index.ts index 838aa505619..a926de84cf7 100644 --- a/packages/util-config-provider/src/index.ts +++ b/packages/util-config-provider/src/index.ts @@ -1 +1,3 @@ export * from "./booleanSelector"; +export * from "./numberSelector"; +export * from "./types"; diff --git a/packages/util-config-provider/src/numberSelector.spec.ts b/packages/util-config-provider/src/numberSelector.spec.ts new file mode 100644 index 00000000000..d18853ecb2c --- /dev/null +++ b/packages/util-config-provider/src/numberSelector.spec.ts @@ -0,0 +1,32 @@ +import { numberSelector } from "./numberSelector"; +import { SelectorType } from "./types"; + +describe(numberSelector.name, () => { + const key = "key"; + const obj: { [key]: any } = {} as any; + + describe.each(Object.entries(SelectorType))(`Selector %s`, (selectorKey, selectorValue) => { + beforeEach(() => { + delete obj[key]; + }); + + it(`should return undefined if ${key} is not defined`, () => { + expect(numberSelector(obj, key, SelectorType[selectorKey])).toBeUndefined(); + }); + + it.each([ + [0, "0"], + [1, "1"], + ])(`should return number %s if ${key}="%s"`, (output, input) => { + obj[key] = input; + expect(numberSelector(obj, key, SelectorType[selectorKey])).toBe(output); + }); + + it.each(["yes", "no", undefined, null, void 0, ""])(`should throw if ${key}=%s`, (input) => { + obj[key] = input; + expect(() => numberSelector(obj, key, SelectorType[selectorKey])).toThrow( + new TypeError(`Cannot load ${selectorValue} '${key}'. Expected number, got '${obj[key]}'.`) + ); + }); + }); +}); diff --git a/packages/util-config-provider/src/numberSelector.ts b/packages/util-config-provider/src/numberSelector.ts new file mode 100644 index 00000000000..3c74dd85546 --- /dev/null +++ b/packages/util-config-provider/src/numberSelector.ts @@ -0,0 +1,19 @@ +import { SelectorType } from "./types"; + +/** + * Returns number value for string value, if the string is defined in obj[key]. + * Returns undefined, if obj[key] is not defined. + * Throws error for all other cases. + * + * @internal + */ +export const numberSelector = (obj: Record, key: string, type: SelectorType) => { + if (!(key in obj)) return undefined; + + const numberValue = parseInt(obj[key] as string, 10); + if (Number.isNaN(numberValue)) { + throw new TypeError(`Cannot load ${type} '${key}'. Expected number, got '${obj[key]}'.`); + } + + return numberValue; +}; diff --git a/packages/util-config-provider/src/types.ts b/packages/util-config-provider/src/types.ts new file mode 100644 index 00000000000..8cea82e5cd1 --- /dev/null +++ b/packages/util-config-provider/src/types.ts @@ -0,0 +1,4 @@ +export enum SelectorType { + ENV = "env", + CONFIG = "shared config entry", +}