Skip to content

Commit b6b802a

Browse files
committed
chore: add utility stringUnionSelector
1 parent 5156e60 commit b6b802a

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { SelectorType, stringUnionSelector } from "./stringUnionSelector";
2+
3+
describe(stringUnionSelector.name, () => {
4+
const key = "key";
5+
const value = "VALUE";
6+
const obj: { [key]: any } = {} as any;
7+
const union = { [key]: value };
8+
9+
describe.each(Object.entries(SelectorType))(`Selector %s`, (selectorKey, selectorValue) => {
10+
beforeEach(() => {
11+
delete obj[key];
12+
});
13+
14+
it(`should return undefined if ${key} is not defined`, () => {
15+
// @ts-expect-error Element implicitly has an 'any' type
16+
expect(stringUnionSelector(obj, key, union, SelectorType[selectorKey])).toBeUndefined();
17+
});
18+
19+
it.each([
20+
[value, value],
21+
[value, value.toLowerCase()],
22+
[value, [...value].map((c, i) => (i % 2 === 0 ? c.toLowerCase() : c.toUpperCase())).join("")],
23+
])(`should return number %s if ${key}="%s"`, (output, input) => {
24+
obj[key] = input;
25+
// @ts-expect-error Element implicitly has an 'any' type
26+
expect(stringUnionSelector(obj, key, union, SelectorType[selectorKey])).toBe(output);
27+
});
28+
29+
// Thows if the value is something other than different case.
30+
it.each(["value1", "1value", [...value].reverse().join("")])(`should throw if ${key}=%s`, (input) => {
31+
obj[key] = input;
32+
// @ts-expect-error Element implicitly has an 'any' type
33+
expect(() => stringUnionSelector(obj, key, union, SelectorType[selectorKey])).toThrow(
34+
new TypeError(
35+
`Cannot load ${selectorValue} '${key}'. Expected one of ${Object.values(union)}, got '${obj[key]}'.`
36+
)
37+
);
38+
});
39+
});
40+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export enum SelectorType {
2+
ENV = "env",
3+
CONFIG = "shared config entry",
4+
}
5+
6+
/**
7+
* Returns undefined, if obj[key] is not defined.
8+
* Returns string value, if the string is defined in obj[key] and it's uppercase matches union value.
9+
* Throws error for all other cases.
10+
*
11+
* @internal
12+
*/
13+
export const stringUnionSelector = (
14+
obj: Record<string, string | undefined>,
15+
key: string,
16+
union: Record<string, string>,
17+
type: SelectorType
18+
) => {
19+
if (!(key in obj)) return undefined;
20+
21+
const value = obj[key]!.toUpperCase();
22+
if (!Object.values(union).includes(value)) {
23+
throw new TypeError(`Cannot load ${type} '${key}'. Expected one of ${Object.values(union)}, got '${obj[key]}'.`);
24+
}
25+
26+
return value;
27+
};

0 commit comments

Comments
 (0)