Skip to content

Commit

Permalink
Fix mapped options using TS enums as a map
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit0 committed Sep 5, 2021
1 parent c901dbc commit 664e27c
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 10 deletions.
16 changes: 9 additions & 7 deletions src/lib/utils/options/declaration.ts
Expand Up @@ -380,14 +380,17 @@ const converters: {
return strArrValue;
},
[ParameterType.Map](value, option) {
const key = String(value).toLowerCase();
const key = String(value);
if (option.map instanceof Map) {
if (option.map.has(key)) {
return option.map.get(key);
} else if ([...option.map.values()].includes(value)) {
return value;
}
} else if (key in option.map) {
if (isTsNumericEnum(option.map) && typeof value === "number") {
return value;
}
return option.map[key];
} else if (Object.values(option.map).includes(value)) {
return value;
Expand Down Expand Up @@ -505,6 +508,10 @@ function resolveModulePaths(modules: readonly string[], configPath: string) {
});
}

function isTsNumericEnum(map: Record<string, any>) {
return Object.values(map).every((key) => map[map[key]] === key);
}

/**
* Returns an error message for a map option, indicating that a given value was not one of the values within the map.
* @param map The values for the option.
Expand All @@ -516,15 +523,10 @@ function getMapError(
name: string
): string {
let keys = map instanceof Map ? [...map.keys()] : Object.keys(map);
const getString = (key: string) =>
String(map instanceof Map ? map.get(key) : map[key]);

// If the map is a TS numeric enum we need to filter out the numeric keys.
// TS numeric enums have the property that every key maps to a value, which maps back to that key.
if (
!(map instanceof Map) &&
keys.every((key) => getString(getString(key)) === key)
) {
if (!(map instanceof Map) && isTsNumericEnum(map)) {
// This works because TS enum keys may not be numeric.
keys = keys.filter((key) => Number.isNaN(parseInt(key, 10)));
}
Expand Down
2 changes: 0 additions & 2 deletions src/test/.editorconfig

This file was deleted.

13 changes: 12 additions & 1 deletion src/test/utils/options/options.test.ts
@@ -1,4 +1,4 @@
import { Logger, Options, ParameterType } from "../../../lib/utils";
import { Logger, LogLevel, Options, ParameterType } from "../../../lib/utils";
import {
BindOption,
MapDeclarationOption,
Expand Down Expand Up @@ -94,6 +94,17 @@ describe("Options", () => {
throws(() => options.setValue("mapped" as any, "nonsense" as any));
});

it("Handles mapped enums properly", () => {
const options = new Options(new Logger());
options.addDefaultDeclarations();

equal(options.getValue("logLevel"), LogLevel.Info);
options.setValue("logLevel", LogLevel.Error);
equal(options.getValue("logLevel"), LogLevel.Error);
options.setValue("logLevel", "Verbose");
equal(options.getValue("logLevel"), LogLevel.Verbose);
});

it("Supports directly getting values", () => {
equal(options.getRawValues().entryPoints, []);
});
Expand Down

0 comments on commit 664e27c

Please sign in to comment.