combo: convert instance and GitHub configs (#1820)

Summary:
This patch converts the `instanceConfig` and `github/config` parsers
from hand-written traversals to combinator-based structures. The
resulting code is much simpler and easier to read.

Test Plan:
Running the `sc2` CLI for `load` and `graph` still works in the happy
path, with the expected errors if keys in the config files are changed
to the wrong strings.

wchargin-branch: combo-instance-github
This commit is contained in:
William Chargin 2020-05-30 16:04:04 -07:00 committed by GitHub
parent 272af9db38
commit 109ebb0417
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 46 deletions

View File

@ -1,5 +1,6 @@
// @flow
import * as Combo from "../util/combo";
import {CliPlugin} from "./cliPlugin";
import {bundledPlugins as getAllBundledPlugins} from "./bundledPlugins";
@ -19,37 +20,25 @@ export type RawInstanceConfig = {|
// dependencies.
export type BundledPluginSpec = string;
type JsonObject =
| string
| number
| boolean
| null
| JsonObject[]
| {[string]: JsonObject};
export function parse(raw: JsonObject): InstanceConfig {
if (raw == null || typeof raw !== "object" || Array.isArray(raw)) {
throw new Error("bad config: " + JSON.stringify(raw));
}
const {bundledPlugins: rawBundledPlugins} = raw;
if (!Array.isArray(rawBundledPlugins)) {
console.warn(JSON.stringify(raw));
throw new Error(
"bad bundled plugins: " + JSON.stringify(rawBundledPlugins)
);
}
const parser: Combo.Parser<InstanceConfig> = (() => {
const C = Combo;
function makePluginMap(bundledPluginNames) {
const allBundledPlugins = getAllBundledPlugins();
const bundledPlugins = new Map();
for (const name of rawBundledPlugins) {
if (typeof name !== "string") {
throw new Error("bad bundled plugin: " + JSON.stringify(name));
}
for (const name of bundledPluginNames) {
const plugin = allBundledPlugins[name];
if (plugin == null) {
throw new Error("bad bundled plugin: " + JSON.stringify(name));
}
bundledPlugins.set(name, plugin);
}
const result = {bundledPlugins};
return result;
return bundledPlugins;
}
return C.object({
bundledPlugins: C.fmap(C.array(C.string), makePluginMap),
});
})();
export function parse(raw: Combo.JsonObject): InstanceConfig {
return parser.parseOrThrow(raw);
}

View File

@ -1,5 +1,6 @@
// @flow
import * as Combo from "../../util/combo";
import {type RepoId, stringToRepoId} from "./repoId";
export type GithubConfig = {|
@ -20,19 +21,16 @@ type JsonObject =
| JsonObject[]
| {[string]: JsonObject};
export function parse(raw: JsonObject): GithubConfig {
if (raw == null || typeof raw !== "object" || Array.isArray(raw)) {
throw new Error("bad config: " + JSON.stringify(raw));
}
const {repositories} = raw;
if (!Array.isArray(repositories)) {
throw new Error("bad repositories: " + JSON.stringify(repositories));
}
const repoIds = repositories.map((x) => {
if (typeof x !== "string") {
throw new Error("bad repository: " + JSON.stringify(x));
}
return stringToRepoId(x);
const parser: Combo.Parser<GithubConfig> = (() => {
const C = Combo;
return C.object({
repoIds: C.rename(
"repositories",
C.array(C.fmap(C.string, stringToRepoId))
),
});
return {repoIds};
})();
export function parse(raw: Combo.JsonObject): GithubConfig {
return parser.parseOrThrow(raw);
}