@@ -4,6 +4,8 @@ import type {
4
4
ResolveFnOutput ,
5
5
ResolveHookContext ,
6
6
} from 'node:module' ;
7
+ import type { PackageJson } from 'type-fest' ;
8
+ import { readJsonFile } from '../../utils/read-json-file.js' ;
7
9
import { resolveTsPath } from '../../utils/resolve-ts-path.js' ;
8
10
import type { NodeError } from '../../types.js' ;
9
11
import { tsconfigPathsMatcher , allowJs } from '../../utils/tsconfig.js' ;
@@ -111,6 +113,33 @@ const tryDirectory = async (
111
113
}
112
114
} ;
113
115
116
+ const tryTsPaths = async (
117
+ url : string ,
118
+ context : ResolveHookContext ,
119
+ nextResolve : NextResolve ,
120
+ ) => {
121
+ const tsPaths = resolveTsPath ( url ) ;
122
+ if ( ! tsPaths ) {
123
+ return ;
124
+ }
125
+
126
+ for ( const tsPath of tsPaths ) {
127
+ try {
128
+ return await resolveMissingFormat (
129
+ await nextResolve ( tsPath , context ) ,
130
+ ) ;
131
+ } catch ( error ) {
132
+ const { code } = error as NodeError ;
133
+ if (
134
+ code !== 'ERR_MODULE_NOT_FOUND'
135
+ && code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED'
136
+ ) {
137
+ throw error ;
138
+ }
139
+ }
140
+ }
141
+ } ;
142
+
114
143
export const resolve : resolve = async (
115
144
specifier ,
116
145
context ,
@@ -172,23 +201,9 @@ export const resolve: resolve = async (
172
201
)
173
202
) {
174
203
// TODO: When guessing the .ts extension in a package, should it guess if there's an export map?
175
- const tsPaths = resolveTsPath ( specifier ) ;
176
- if ( tsPaths ) {
177
- for ( const tsPath of tsPaths ) {
178
- try {
179
- return await resolveMissingFormat (
180
- await nextResolve ( tsPath , context ) ,
181
- ) ;
182
- } catch ( error ) {
183
- const { code } = error as NodeError ;
184
- if (
185
- code !== 'ERR_MODULE_NOT_FOUND'
186
- && code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED'
187
- ) {
188
- throw error ;
189
- }
190
- }
191
- }
204
+ const resolved = await tryTsPaths ( specifier , context , nextResolve ) ;
205
+ if ( resolved ) {
206
+ return resolved ;
192
207
}
193
208
}
194
209
@@ -212,7 +227,8 @@ export const resolve: resolve = async (
212
227
error instanceof Error
213
228
&& ! recursiveCall
214
229
) {
215
- const { code } = error as NodeError ;
230
+ const nodeError = error as NodeError ;
231
+ const { code } = nodeError ;
216
232
if ( code === 'ERR_UNSUPPORTED_DIR_IMPORT' ) {
217
233
try {
218
234
return await tryDirectory ( specifier , context , nextResolve ) ;
@@ -224,9 +240,48 @@ export const resolve: resolve = async (
224
240
}
225
241
226
242
if ( code === 'ERR_MODULE_NOT_FOUND' ) {
227
- try {
228
- return await tryExtensions ( specifier , context , nextResolve ) ;
229
- } catch { }
243
+ // Resolving .js -> .ts in exports map
244
+ if ( nodeError . url ) {
245
+ const resolved = await tryTsPaths ( nodeError . url , context , nextResolve ) ;
246
+ if ( resolved ) {
247
+ return resolved ;
248
+ }
249
+ } else {
250
+ const isExportPath = error . message . match ( / ^ C a n n o t f i n d m o d u l e ' ( [ ^ ' ] + ) ' / ) ;
251
+ if ( isExportPath ) {
252
+ const [ , exportPath ] = isExportPath ;
253
+ const resolved = await tryTsPaths ( exportPath , context , nextResolve ) ;
254
+ if ( resolved ) {
255
+ return resolved ;
256
+ }
257
+ }
258
+
259
+ const isPackagePath = error . message . match ( / ^ C a n n o t f i n d p a c k a g e ' ( [ ^ ' ] + ) ' / ) ;
260
+ if ( isPackagePath ) {
261
+ const [ , packageJsonPath ] = isPackagePath ;
262
+ const packageJsonUrl = pathToFileURL ( packageJsonPath ) ;
263
+
264
+ if ( ! packageJsonUrl . pathname . endsWith ( '/package.json' ) ) {
265
+ packageJsonUrl . pathname += '/package.json' ;
266
+ }
267
+
268
+ const packageJson = await readJsonFile < PackageJson > ( packageJsonUrl ) ;
269
+ if ( packageJson ?. main ) {
270
+ const resolvedMain = new URL ( packageJson . main , packageJsonUrl ) ;
271
+ const resolved = await tryTsPaths ( resolvedMain . toString ( ) , context , nextResolve ) ;
272
+ if ( resolved ) {
273
+ return resolved ;
274
+ }
275
+ }
276
+ }
277
+ }
278
+
279
+ // If not bare specifier
280
+ if ( acceptsQuery ) {
281
+ try {
282
+ return await tryExtensions ( specifier , context , nextResolve ) ;
283
+ } catch { }
284
+ }
230
285
}
231
286
}
232
287
0 commit comments