@@ -69,6 +69,7 @@ let cachedPackageImports: Record<string, string> | null | undefined;
6969
7070function resolveViaTsConfigPaths (
7171 specifier : Specifier ,
72+ parentPath ?: FSAbsolutePath | ResolvedSpecifier ,
7273) : ResolvedSpecifier | null {
7374 if (
7475 specifier . startsWith ( '.' ) ||
@@ -78,7 +79,7 @@ function resolveViaTsConfigPaths(
7879 return null ;
7980 }
8081
81- const tsConfigPaths = getTsConfigPaths ( ) ;
82+ const tsConfigPaths = getTsConfigPaths ( parentPath ) ;
8283 if ( ! tsConfigPaths ) return null ;
8384
8485 for ( const entry of tsConfigPaths . entries ) {
@@ -102,49 +103,62 @@ function resolveViaTsConfigPaths(
102103 return null ;
103104}
104105
105- function getTsConfigPaths ( ) : TsConfigPaths | null {
106- if ( cachedTsConfigPaths !== undefined ) return cachedTsConfigPaths ;
107-
108- try {
109- const raw = readFileSync (
110- resolvePath ( process . cwd ( ) , 'tsconfig.json' ) ,
111- 'utf8' ,
112- ) ;
113- const json = parseJsonc ( raw ) as {
114- compilerOptions ?: {
115- baseUrl ?: string ;
116- paths ?: Record < string , string [ ] > ;
106+ function getTsConfigPaths ( parentPath ?: FSAbsolutePath | ResolvedSpecifier ) : TsConfigPaths | null {
107+ if ( cachedTsConfigPaths !== undefined && ! parentPath ) return cachedTsConfigPaths ;
108+
109+ const tryRead = ( baseDir : string ) => {
110+ try {
111+ const raw = readFileSync ( resolvePath ( baseDir , 'tsconfig.json' ) , 'utf8' ) ;
112+ const json = parseJsonc ( raw ) as {
113+ compilerOptions ?: {
114+ baseUrl ?: string ;
115+ paths ?: Record < string , string [ ] > ;
116+ } ;
117117 } ;
118- } ;
119118
120- const paths = json . compilerOptions ?. paths ;
121- if ( ! paths ) {
122- cachedTsConfigPaths = null ;
123- return cachedTsConfigPaths ;
124- }
119+ const paths = json . compilerOptions ?. paths ;
120+ if ( ! paths ) return null ;
125121
126- const baseDir = resolvePath (
127- process . cwd ( ) ,
128- json . compilerOptions ?. baseUrl ?? '.' ,
129- ) ;
130- const entries : TsConfigPathMap [ ] = [ ] ;
122+ const baseDirResolved = resolvePath ( baseDir , json . compilerOptions ?. baseUrl ?? '.' ) ;
123+ const entries : TsConfigPathMap [ ] = [ ] ;
131124
132- for ( const [ pattern , targets ] of Object . entries ( paths ) ) {
133- if ( ! targets . length ) continue ;
125+ for ( const [ pattern , targets ] of Object . entries ( paths ) ) {
126+ if ( ! targets . length ) continue ;
134127
135- const firstTarget = targets [ 0 ] ;
136- const [ keyPrefix , keySuffix ] = splitStarPattern ( pattern ) ;
137- const [ targetPrefix , targetSuffix ] = splitStarPattern ( firstTarget ) ;
128+ const firstTarget = targets [ 0 ] ;
129+ const [ keyPrefix , keySuffix ] = splitStarPattern ( pattern ) ;
130+ const [ targetPrefix , targetSuffix ] = splitStarPattern ( firstTarget ) ;
138131
139- entries . push ( { keyPrefix, keySuffix, targetPrefix, targetSuffix } ) ;
140- }
132+ entries . push ( { keyPrefix, keySuffix, targetPrefix, targetSuffix } ) ;
133+ }
141134
142- cachedTsConfigPaths = { baseDir, entries } ;
143- return cachedTsConfigPaths ;
144- } catch {
145- cachedTsConfigPaths = null ;
146- return cachedTsConfigPaths ;
135+ return { baseDir : baseDirResolved , entries } ;
136+ } catch {
137+ return null ;
138+ }
139+ } ;
140+
141+ // If parentPath is provided, prefer tsconfig relative to that file's directory.
142+ if ( parentPath ) {
143+ try {
144+ const startingDir = isAbsolute ( parentPath )
145+ ? dirname ( parentPath as string )
146+ : dirname ( fileURLToPath ( parentPath as string ) ) ;
147+ const result = tryRead ( startingDir ) ;
148+ if ( result ) {
149+ // cache only when not using parentPath (we might be in multiple files)
150+ return result ;
151+ }
152+ } catch {
153+ // ignore and fall back
154+ }
147155 }
156+
157+ if ( cachedTsConfigPaths !== undefined ) return cachedTsConfigPaths ;
158+
159+ const fallback = tryRead ( process . cwd ( ) ) ;
160+ cachedTsConfigPaths = fallback ;
161+ return cachedTsConfigPaths ;
148162}
149163
150164function resolveViaPackageImports (
0 commit comments