From c4978e948c5b0cebf85ef9af62da523169994bf9 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Sat, 28 Nov 2020 02:02:15 -0800 Subject: [PATCH] feature(gatsby): Warn when there's unknown flags in gatsby-config.js & suggest fixes to potential typos (#28326) * feature(gatsby): Warn when there's unknown flags in gatsby-config.js & suggest fixes to potential typos * Update packages/gatsby/src/utils/handle-flags.ts Co-authored-by: Michal Piechowiak * Reformat message per @pieh's suggestion * make typescript happy Co-authored-by: Michal Piechowiak --- examples/using-drupal/gatsby-config.js | 3 ++ packages/gatsby/src/services/initialize.ts | 6 ++- .../__snapshots__/handle-flags.ts.snap | 21 ++++++++ .../src/utils/__tests__/handle-flags.ts | 9 ++++ packages/gatsby/src/utils/handle-flags.ts | 53 ++++++++++++++++++- 5 files changed, 89 insertions(+), 3 deletions(-) diff --git a/examples/using-drupal/gatsby-config.js b/examples/using-drupal/gatsby-config.js index cae0ee679d15e..5940d4f477a54 100644 --- a/examples/using-drupal/gatsby-config.js +++ b/examples/using-drupal/gatsby-config.js @@ -1,4 +1,7 @@ module.exports = { + flags: { + DEV_SSR: true, + }, siteMetadata: { title: `Gatsby with Drupal`, }, diff --git a/packages/gatsby/src/services/initialize.ts b/packages/gatsby/src/services/initialize.ts index 82914ac1885b0..48ada570b9c4a 100644 --- a/packages/gatsby/src/services/initialize.ts +++ b/packages/gatsby/src/services/initialize.ts @@ -186,11 +186,15 @@ export async function initialize({ if (config && config.flags) { const availableFlags = require(`../utils/flags`).default // Get flags - const { enabledConfigFlags, message } = handleFlags( + const { enabledConfigFlags, unknownFlagMessage, message } = handleFlags( availableFlags, config.flags ) + if (unknownFlagMessage !== ``) { + reporter.warn(unknownFlagMessage) + } + // set process.env for each flag enabledConfigFlags.forEach(flag => { process.env[flag.env] = `true` diff --git a/packages/gatsby/src/utils/__tests__/__snapshots__/handle-flags.ts.snap b/packages/gatsby/src/utils/__tests__/__snapshots__/handle-flags.ts.snap index b07d4965c35ee..23541c5a3e911 100644 --- a/packages/gatsby/src/utils/__tests__/__snapshots__/handle-flags.ts.snap +++ b/packages/gatsby/src/utils/__tests__/__snapshots__/handle-flags.ts.snap @@ -1,5 +1,25 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`handle flags returns a message about unknown flags in the config 1`] = ` +Object { + "enabledConfigFlags": Array [ + Object { + "command": "all", + "description": "test", + "env": "GATSBY_EXPERIMENTAL_SOMETHING_COOL", + "name": "ALL_COMMANDS", + "umbrellaIssue": "test", + }, + ], + "message": "The following flags are active: +- ALL_COMMANDS · (Umbrella Issue (test)) · test +", + "unknownFlagMessage": "The following flag(s) found in your gatsby-config.js are not known: +- FASTLY_DEV (did you mean: FAST_DEV) +- SUPER_COOL_FLAG", +} +`; + exports[`handle flags returns validConfigFlags and a message 1`] = ` Object { "enabledConfigFlags": Array [ @@ -42,5 +62,6 @@ Object { - DEV_SSR · (Umbrella Issue (https://github.com/gatsbyjs/gatsby/discussions/28138)) · SSR pages on full reloads during develop. Helps you detect SSR bugs and fix them without needing to do full builds. - QUERY_ON_DEMAND · (Umbrella Issue (https://github.com/gatsbyjs/gatsby/discussions/27620)) · Only run queries when needed instead of running all queries upfront. Speeds starting the develop server. ", + "unknownFlagMessage": "", } `; diff --git a/packages/gatsby/src/utils/__tests__/handle-flags.ts b/packages/gatsby/src/utils/__tests__/handle-flags.ts index 25322498bb4ea..7afb54e37139b 100644 --- a/packages/gatsby/src/utils/__tests__/handle-flags.ts +++ b/packages/gatsby/src/utils/__tests__/handle-flags.ts @@ -84,4 +84,13 @@ describe(`handle flags`, () => { handleFlags(activeFlags, configFlags, `build`).enabledConfigFlags ).toHaveLength(1) }) + + it(`returns a message about unknown flags in the config`, () => { + const unknownConfigFlags = handleFlags( + activeFlags, + { ALL_COMMANDS: true, FASTLY_DEV: true, SUPER_COOL_FLAG: true }, + `develop` + ) + expect(unknownConfigFlags).toMatchSnapshot() + }) }) diff --git a/packages/gatsby/src/utils/handle-flags.ts b/packages/gatsby/src/utils/handle-flags.ts index c2fcf0321a69e..ca68f6534fc53 100644 --- a/packages/gatsby/src/utils/handle-flags.ts +++ b/packages/gatsby/src/utils/handle-flags.ts @@ -3,6 +3,8 @@ import { isCI } from "gatsby-core-utils" import realTerminalLink from "terminal-link" import { IFlag } from "./flags" import chalk from "chalk" +import { commaListsAnd } from "common-tags" +import { distance } from "fastest-levenshtein" const terminalLink = (text, url): string => { if (process.env.NODE_ENV === `test`) { @@ -16,11 +18,54 @@ const handleFlags = ( flags: Array, configFlags: Record, executingCommand = process.env.gatsby_executing_command -): { enabledConfigFlags: Array; message: string } => { +): { + enabledConfigFlags: Array + unknownFlagMessage: string + message: string +} => { // Prepare config flags. // Filter out any flags that are set to false. const availableFlags = new Map() flags.forEach(flag => availableFlags.set(flag.name, flag)) + + // Find unknown flags someone has in their config to warn them about. + const unknownConfigFlags: Array = [] + for (const flagName in configFlags) { + if (availableFlags.has(flagName)) { + continue + } + let flagWithMinDistance + let minDistance + for (const availableFlag of flags) { + if (availableFlag.name !== flagName) { + const distanceToFlag = distance(flagName, availableFlag.name) + if (!flagWithMinDistance || distanceToFlag < minDistance) { + flagWithMinDistance = availableFlag.name + minDistance = distanceToFlag + } + } + } + + if (flagName) { + unknownConfigFlags.push({ + flag: flagName, + didYouMean: + flagWithMinDistance && minDistance < 4 ? flagWithMinDistance : ``, + }) + } + } + + let unknownFlagMessage = `` + if (unknownConfigFlags.length > 0) { + unknownFlagMessage = commaListsAnd`The following flag(s) found in your gatsby-config.js are not known:` + unknownConfigFlags.forEach( + flag => + (unknownFlagMessage += `\n- ${flag?.flag}${ + flag?.didYouMean ? ` (did you mean: ${flag?.didYouMean})` : `` + }`) + ) + } + let enabledConfigFlags = Object.keys(configFlags) .filter(name => configFlags[name] && availableFlags.has(name)) .map(flagName => availableFlags.get(flagName)) @@ -85,7 +130,11 @@ const handleFlags = ( message += `\n` } - return { enabledConfigFlags, message } + return { + enabledConfigFlags, + message, + unknownFlagMessage, + } } export default handleFlags