1- import { dirname , join , posix , resolve as pResolve } from 'path' ;
1+ import { dirname , join , posix , relative , resolve as pResolve } from 'path' ;
22import { promises as fs } from 'fs' ;
33import { resolve , legacy as resolveLegacy } from 'resolve.exports' ;
44import {
@@ -9,7 +9,11 @@ import {
99// Only used for node_modules
1010const resolveCache = new Map < string , ResolveResult > ( ) ;
1111
12- const resolveCacheKey = ( id : string , root : string ) => `${ id } \0\0${ root } ` ;
12+ const resolveCacheKey = (
13+ id : string ,
14+ importer : string | undefined ,
15+ root : string ,
16+ ) => `${ id } \n${ importer } \n${ root } ` ;
1317
1418/**
1519 * Attempts to implement a combination of:
@@ -22,7 +26,7 @@ export const nodeResolve = async (
2226 importer : string ,
2327 root : string ,
2428) => {
25- if ( isBareImport ( id ) ) return resolveFromNodeModules ( id , root ) ;
29+ if ( isBareImport ( id ) ) return resolveFromNodeModules ( id , importer , root ) ;
2630 if ( isRelativeOrAbsoluteImport ( id ) )
2731 return resolveRelativeOrAbsolute ( id , importer ) ;
2832} ;
@@ -108,9 +112,10 @@ interface ResolveResult {
108112
109113export const resolveFromNodeModules = async (
110114 id : string ,
115+ importer : string | undefined ,
111116 root : string ,
112117) : Promise < ResolveResult > => {
113- const cacheKey = resolveCacheKey ( id , root ) ;
118+ const cacheKey = resolveCacheKey ( id , importer , root ) ;
114119 const cached = resolveCache . get ( cacheKey ) ;
115120 if ( cached ) return cached ;
116121 const pathChunks = id . split ( posix . sep ) ;
@@ -120,10 +125,29 @@ export const resolveFromNodeModules = async (
120125 // Path within imported module
121126 const subPath = join ( ...pathChunks . slice ( isNpmNamespace ? 2 : 1 ) ) ;
122127
123- const pkgDir = join ( root , 'node_modules' , ...packageName ) ;
124- const stats = await stat ( pkgDir ) ;
125- if ( ! stats || ! stats . isDirectory ( ) )
126- throw new Error ( `Could not find ${ id } in node_modules` ) ;
128+ const realRoot = await fs . realpath ( root ) . catch ( ( ) => root ) ;
129+
130+ // Walk up folder by folder until a folder is found with <folder>/node_modules/<pkgName>
131+ // i.e. for 'asdf' from a/b/c.js look at
132+ // a/b/node_modules/asdf,
133+ // a/node_modules/asdf,
134+ // node_modules/asdf,
135+
136+ let pkgDir : string | undefined ;
137+ let scanDir = importer
138+ ? await fs
139+ . realpath ( importer )
140+ . then ( ( realImporter ) => relative ( realRoot , realImporter ) )
141+ . catch ( ( ) => relative ( root , importer ) )
142+ : '.' ;
143+ while ( ! pkgDir || ! ( await stat ( pkgDir ) ) ?. isDirectory ( ) ) {
144+ if ( scanDir === '.' || scanDir . startsWith ( '..' ) ) {
145+ throw new Error ( `Could not find ${ id } in node_modules` ) ;
146+ }
147+ // Not found; go up a level and try again
148+ scanDir = dirname ( scanDir ) ;
149+ pkgDir = join ( root , scanDir , 'node_modules' , ...packageName ) ;
150+ }
127151
128152 const pkgJson = await readPkgJson ( pkgDir ) ;
129153 const main = readMainFields ( pkgJson , subPath , true ) ;
@@ -144,7 +168,10 @@ export const resolveFromNodeModules = async (
144168 version ? `${ normalizedPkgName } @${ version } ` : normalizedPkgName ,
145169 subPath ,
146170 ) ;
147- const resolved : ResolveResult = { path : result , idWithVersion } ;
171+ const resolved : ResolveResult = {
172+ path : await fs . realpath ( result ) ,
173+ idWithVersion,
174+ } ;
148175 resolveCache . set ( cacheKey , resolved ) ;
149176 return resolved ;
150177 }
0 commit comments