11// @ts -check
22const path = require ( 'path' ) ;
3+ const process = require ( 'process' ) ;
34const logger = require ( 'loglevel' ) ;
45const {
56 getLanguageNames,
@@ -13,6 +14,7 @@ const {
1314const { getHighestBuiltinLanguageId } = require ( './storeUtils' ) ;
1415const unzipDir = path . resolve ( __dirname , '../lib/extensions' ) ;
1516const requireMain = createRequire ( require . main . filename ) ;
17+ const requireCwd = createRequire ( path . join ( process . cwd ( ) , 'index.js' ) ) ;
1618
1719/**
1820 * @param {string } packageJsonPath
@@ -105,7 +107,7 @@ async function mergeCache(cache, key, value) {
105107 * @param {Host } host
106108 */
107109async function getExtensionPackageJsonPath ( specifier , host ) {
108- const absolute = path . isAbsolute ( specifier ) ? specifier : requireMain . resolve ( path . join ( specifier , 'package.json' ) ) ;
110+ const absolute = path . isAbsolute ( specifier ) ? specifier : requireResolveExtension ( specifier ) ;
109111 const ext = path . extname ( absolute ) ;
110112 if ( ext . toLowerCase ( ) === '.vsix' || ext . toLowerCase ( ) === '.zip' ) {
111113 const outDir = path . join ( unzipDir , path . basename ( absolute , ext ) ) ;
@@ -137,6 +139,33 @@ async function getExtensionPackageJsonPath(specifier, host) {
137139 }
138140}
139141
142+ /**
143+ * We want to resolve the extension from the context of the user’s gatsby-config,
144+ * but this turns out to be difficult. Ideally, gatsby and this plugin are installed
145+ * in the same node_modules directory as the extension, but gatsby could be invoked
146+ * globally, and this plugin could be npm linked. If both of those things happen, we
147+ * can also try resolving from the current working directory. One of these will
148+ * probably always work.
149+ * @param {string } specifier
150+ */
151+ function requireResolveExtension ( specifier ) {
152+ return (
153+ tryResolve ( require ) ||
154+ tryResolve ( requireMain ) ||
155+ tryResolve ( requireCwd ) ||
156+ require . resolve ( path . join ( specifier , 'package.json' ) )
157+ ) ; // If none work, throw the best error stack
158+
159+ /** @param {NodeRequire } req */
160+ function tryResolve ( req ) {
161+ try {
162+ return req . resolve ( path . join ( specifier , 'package.json' ) ) ;
163+ } catch ( _ ) {
164+ return undefined ;
165+ }
166+ }
167+ }
168+
140169/**
141170 * @param {string[] } extensions
142171 * @param {Host } host
0 commit comments