Skip to content

Commit

Permalink
add better warnings for union types
Browse files Browse the repository at this point in the history
  • Loading branch information
hipstersmoothie committed Feb 18, 2021
1 parent acbabd5 commit e3aed20
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,12 @@ Found unknown configuration keys: types.doc
",
]
`;

exports[`validatePlugin should validate plugin configuration - union 1`] = `
Array [
"\\"test-plugin\\"
Found missing configuration keys: when using auth you must also provide channels
",
]
`;
53 changes: 53 additions & 0 deletions packages/core/src/__tests__/validate-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,59 @@ describe("validatePlugin", () => {
).toMatchSnapshot();
});

test("should validate plugin configuration - union", async () => {
const hook: ValidatePluginHook = new AsyncSeriesBailHook([
"name",
"options",
]);

const basePluginOptions = t.partial({
/** URL of the slack to post to */
url: t.string,
/** Who to bother when posting to the channel */
atTarget: t.string,
/** Allow users to opt into having prereleases posted to slack */
publishPreRelease: t.boolean,
/** Additional Title to add at the start of the slack message */
title: t.string,
});

const appPluginOptions = t.intersection([
t.interface({
/** Marks we are gonna use app auth */
auth: t.literal("app"),
/** Channels to post */
channels: t.array(t.string),
}),
basePluginOptions,
]);

const pluginOptions = t.union([basePluginOptions, appPluginOptions]);

hook.tapPromise("test", async (name, options) => {
if (name === "test-plugin") {
return validatePluginConfiguration(
"test-plugin",
pluginOptions,
options
);
}
});

// Check no validation issues with base options
expect(
await validatePlugins(hook, {
plugins: [["test-plugin", { url: "foo" }]],
})
).toStrictEqual([]);
// Check no validation issues with intersected options
expect(
await validatePlugins(hook, {
plugins: [["test-plugin", { auth: "app" }]],
})
).toMatchSnapshot();
});

test("should validate plugin configuration - array of configurations", async () => {
const hook: ValidatePluginHook = new AsyncSeriesBailHook([
"name",
Expand Down
34 changes: 33 additions & 1 deletion packages/core/src/validate-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ export const validateIoConfiguration = (
return errors;
}

const exactRc = makeExactType(configDeceleration).decode(rc);
const exactDeclaration = makeExactType(configDeceleration);
const exactRc = exactDeclaration.decode(rc);

if (!isRight(looseRc) || !isRight(exactRc)) {
return [];
Expand All @@ -247,6 +248,37 @@ export const validateIoConfiguration = (
return [];
}

if (
(exactDeclaration as any)._tag === "UnionType" &&
"types" in exactDeclaration &&
exactDeclaration.types.every(
(type) =>
type._tag === "IntersectionType" || (type as any)._tag === "ExactType"
)
) {
const matchingMember = exactDeclaration.types
.map((t) => t.decode(rc))
.filter((t) => "left" in t)[0];

if (matchingMember && "left" in matchingMember) {
const correct = Object.keys(
matchingMember.left[0].context[0].actual as any
);
const missing =
matchingMember.left[0].context[
matchingMember.left[0].context.length - 1
].key;

return [
`${errorPath(
`"${name}"`
)}\n\nFound missing configuration keys: when using ${chalk.greenBright.bold(
correct.join(", ")
)} you must also provide ${unexpectedValue(missing)}\n`,
];
}
}

return [
`${errorPath(
`"${name}"`
Expand Down

0 comments on commit e3aed20

Please sign in to comment.