diff --git a/packages/gatsby/src/bootstrap/load-plugins/resolve-plugin.ts b/packages/gatsby/src/bootstrap/load-plugins/resolve-plugin.ts index 9cd103b95eca6..1dd78b6708199 100644 --- a/packages/gatsby/src/bootstrap/load-plugins/resolve-plugin.ts +++ b/packages/gatsby/src/bootstrap/load-plugins/resolve-plugin.ts @@ -1,7 +1,6 @@ import path from "path" import fs from "fs" import { slash, createRequireFromPath } from "gatsby-core-utils" -import { sync as existsSync } from "fs-exists-cached" import { warnOnIncompatiblePeerDependency } from "./validate" import { PackageJson } from "../../.." import { IPluginInfo, PluginRef } from "./types" @@ -9,6 +8,7 @@ import { createPluginId } from "./utils/create-id" import { createFileContentHash } from "./utils/create-hash" import reporter from "gatsby-cli/lib/reporter" import { isString } from "lodash" +import { isValidLocalPlugin } from "./utils/is-valid-local-plugin" /** * @param plugin @@ -24,30 +24,26 @@ import { isString } from "lodash" export function resolvePlugin(plugin: PluginRef, rootDir: string): IPluginInfo { const pluginName = isString(plugin) ? plugin : plugin.resolve - // Only find plugins when we're not given an absolute path - if (!existsSync(pluginName) && rootDir) { - // Find the plugin in the local plugins folder - const resolvedPath = slash(path.join(rootDir, `plugins/${pluginName}`)) + // Handle local plugins + const { validLocalPlugin, resolvedLocalPluginPath = `` } = isValidLocalPlugin( + plugin, + rootDir + ) - if (existsSync(resolvedPath)) { - if (existsSync(`${resolvedPath}/package.json`)) { - const packageJSON = JSON.parse( - fs.readFileSync(`${resolvedPath}/package.json`, `utf-8`) - ) as PackageJson - const name = packageJSON.name || pluginName - warnOnIncompatiblePeerDependency(name, packageJSON) + if (validLocalPlugin && resolvedLocalPluginPath) { + const packageJSON = JSON.parse( + fs.readFileSync(`${resolvedLocalPluginPath}/package.json`, `utf-8`) + ) as PackageJson + const name = packageJSON.name || pluginName + warnOnIncompatiblePeerDependency(name, packageJSON) - return { - resolve: resolvedPath, - name, - id: createPluginId(name), - version: - packageJSON.version || createFileContentHash(resolvedPath, `**`), - } - } else { - // Make package.json a requirement for local plugins too - throw new Error(`Plugin ${pluginName} requires a package.json file`) - } + return { + resolve: resolvedLocalPluginPath, + name, + id: createPluginId(name), + version: + packageJSON.version || + createFileContentHash(resolvedLocalPluginPath, `**`), } } diff --git a/packages/gatsby/src/bootstrap/load-plugins/utils/is-valid-local-plugin.ts b/packages/gatsby/src/bootstrap/load-plugins/utils/is-valid-local-plugin.ts new file mode 100644 index 0000000000000..7bbd2ad64bdf6 --- /dev/null +++ b/packages/gatsby/src/bootstrap/load-plugins/utils/is-valid-local-plugin.ts @@ -0,0 +1,34 @@ +import { PluginRef } from "../types" +import { sync as existsSync } from "fs-exists-cached" +import { slash } from "gatsby-core-utils" +import path from "path" + +/** + * Checks if a plugin is a valid local plugin and returns the resolved path if it is. + */ +export function isValidLocalPlugin( + plugin: PluginRef, + rootDir: string +): { validLocalPlugin: boolean; resolvedLocalPluginPath?: string } { + const pluginName = typeof plugin === `string` ? plugin : plugin.resolve + + // Make sure the plugin exists relatively + if (existsSync(pluginName) || !rootDir) { + return { + validLocalPlugin: false, + } + } + + const resolvedPath = slash(path.join(rootDir, `plugins/${pluginName}`)) + const resolvedPackageJson = existsSync(`${resolvedPath}/package.json`) + + // package.json is a requirement for local plugins + if (!resolvedPackageJson) { + throw new Error(`Local plugin ${pluginName} requires a package.json file`) + } + + return { + validLocalPlugin: true, + resolvedLocalPluginPath: resolvedPath, + } +}