@@ -111,7 +111,10 @@ let cachedOptions: InternalResolverOptions | undefined
111
111
let prevCwd : string
112
112
113
113
let mappersCachedOptions : InternalResolverOptions
114
- let mappers : Array < ( ( specifier : string ) => string [ ] ) | null > | undefined
114
+ let mappers : Array < {
115
+ files : Set < string >
116
+ mapperFn : NonNullable < ReturnType < typeof createPathsMatcher > >
117
+ } > = [ ]
115
118
116
119
let resolverCachedOptions : InternalResolverOptions
117
120
let cachedResolver : Resolver | undefined
@@ -159,7 +162,7 @@ export function resolve(
159
162
resolver = cachedResolver
160
163
}
161
164
162
- log ( 'looking for: ' , source )
165
+ log ( 'looking for' , source , 'in' , file )
163
166
164
167
source = removeQuerystring ( source )
165
168
@@ -300,34 +303,35 @@ function getMappedPath(
300
303
paths = [ resolved ]
301
304
}
302
305
} else {
303
- paths = mappers !
304
- . map ( mapper =>
305
- mapper ?.( source ) . map ( item => [
306
- ...extensions . map ( ext => `${ item } ${ ext } ` ) ,
307
- ...originalExtensions . map ( ext => `${ item } /index${ ext } ` ) ,
308
- ] ) ,
309
- )
310
- . flat ( 2 )
311
- . filter ( mappedPath => {
312
- if ( mappedPath === undefined ) {
313
- return false
314
- }
315
-
316
- try {
317
- const stat = fs . statSync ( mappedPath , { throwIfNoEntry : false } )
318
- if ( stat === undefined ) return false
319
- if ( stat . isFile ( ) ) return true
320
-
321
- // Maybe this is a module dir?
322
- if ( stat . isDirectory ( ) ) {
323
- return isModule ( mappedPath )
324
- }
325
- } catch {
326
- return false
306
+ paths = [
307
+ ...new Set (
308
+ mappers
309
+ . filter ( ( { files } ) => files . has ( file ) )
310
+ . map ( ( { mapperFn } ) =>
311
+ mapperFn ( source ) . map ( item => [
312
+ ...extensions . map ( ext => `${ item } ${ ext } ` ) ,
313
+ ...originalExtensions . map ( ext => `${ item } /index${ ext } ` ) ,
314
+ ] ) ,
315
+ )
316
+ . flat ( 2 )
317
+ . map ( toNativePathSeparator ) ,
318
+ ) ,
319
+ ] . filter ( mappedPath => {
320
+ try {
321
+ const stat = fs . statSync ( mappedPath , { throwIfNoEntry : false } )
322
+ if ( stat === undefined ) return false
323
+ if ( stat . isFile ( ) ) return true
324
+
325
+ // Maybe this is a module dir?
326
+ if ( stat . isDirectory ( ) ) {
327
+ return isModule ( mappedPath )
327
328
}
328
-
329
+ } catch {
329
330
return false
330
- } )
331
+ }
332
+
333
+ return false
334
+ } )
331
335
}
332
336
333
337
if ( retry && paths . length === 0 ) {
@@ -367,50 +371,114 @@ function getMappedPath(
367
371
return paths [ 0 ]
368
372
}
369
373
374
+ // eslint-disable-next-line sonarjs/cognitive-complexity
370
375
function initMappers ( options : InternalResolverOptions ) {
371
376
if (
372
- mappers &&
377
+ mappers . length > 0 &&
373
378
mappersCachedOptions === options &&
374
379
prevCwd === process . cwd ( )
375
380
) {
376
381
return
377
382
}
378
383
prevCwd = process . cwd ( )
379
384
380
- const configPaths =
385
+ const configPaths = (
381
386
typeof options . project === 'string'
382
387
? [ options . project ]
383
388
: Array . isArray ( options . project )
384
389
? options . project
385
390
: [ process . cwd ( ) ]
391
+ ) // 'tinyglobby' pattern must have POSIX separator
392
+ . map ( config => replacePathSeparator ( config , path . sep , path . posix . sep ) )
386
393
387
- const ignore = [ '!**/node_modules/**' ]
394
+ // https://github.com/microsoft/TypeScript/blob/df342b7206cb56b56bb3b3aecbb2ee2d2ff7b217/src/compiler/commandLineParser.ts#L3006
395
+ const defaultInclude = [ '**/*' ]
396
+ const defaultIgnore = [ '**/node_modules/**' ]
388
397
389
- // turn glob patterns into paths
398
+ // Turn glob patterns into paths
390
399
const projectPaths = [
391
400
...new Set ( [
392
401
...configPaths . filter ( path => ! isDynamicPattern ( path ) ) ,
393
402
...globSync (
394
- [ ... configPaths . filter ( path => isDynamicPattern ( path ) ) , ... ignore ] ,
403
+ configPaths . filter ( path => isDynamicPattern ( path ) ) ,
395
404
{
396
405
expandDirectories : false ,
406
+ ignore : defaultIgnore ,
407
+ absolute : true ,
397
408
} ,
398
409
) ,
399
410
] ) ,
400
411
]
401
412
402
- mappers = projectPaths . map ( projectPath => {
403
- let tsconfigResult : TsConfigResult | null
413
+ mappers = projectPaths
414
+ . map ( projectPath => {
415
+ let tsconfigResult : TsConfigResult | null
404
416
405
- if ( isFile ( projectPath ) ) {
406
- const { dir, base } = path . parse ( projectPath )
407
- tsconfigResult = getTsconfig ( dir , base )
408
- } else {
409
- tsconfigResult = getTsconfig ( projectPath )
410
- }
417
+ if ( isFile ( projectPath ) ) {
418
+ const { dir, base } = path . parse ( projectPath )
419
+ tsconfigResult = getTsconfig ( dir , base )
420
+ } else {
421
+ tsconfigResult = getTsconfig ( projectPath )
422
+ }
411
423
412
- return tsconfigResult && createPathsMatcher ( tsconfigResult )
413
- } )
424
+ if ( ! tsconfigResult ) {
425
+ // eslint-disable-next-line unicorn/no-useless-undefined
426
+ return undefined
427
+ }
428
+
429
+ const mapperFn = createPathsMatcher ( tsconfigResult )
430
+
431
+ if ( ! mapperFn ) {
432
+ // eslint-disable-next-line unicorn/no-useless-undefined
433
+ return undefined
434
+ }
435
+
436
+ const files =
437
+ tsconfigResult . config . files === undefined &&
438
+ tsconfigResult . config . include === undefined
439
+ ? // Include everything if no files or include options
440
+ globSync ( defaultInclude , {
441
+ ignore : [
442
+ ...( tsconfigResult . config . exclude ?? [ ] ) ,
443
+ ...defaultIgnore ,
444
+ ] ,
445
+ absolute : true ,
446
+ cwd : path . dirname ( tsconfigResult . path ) ,
447
+ } )
448
+ : [
449
+ // https://www.typescriptlang.org/tsconfig/#files
450
+ ...( tsconfigResult . config . files !== undefined &&
451
+ tsconfigResult . config . files . length > 0
452
+ ? tsconfigResult . config . files . map ( file =>
453
+ path . normalize (
454
+ path . resolve ( path . dirname ( tsconfigResult ! . path ) , file ) ,
455
+ ) ,
456
+ )
457
+ : [ ] ) ,
458
+ // https://www.typescriptlang.org/tsconfig/#include
459
+ ...( tsconfigResult . config . include !== undefined &&
460
+ tsconfigResult . config . include . length > 0
461
+ ? globSync ( tsconfigResult . config . include , {
462
+ ignore : [
463
+ ...( tsconfigResult . config . exclude ?? [ ] ) ,
464
+ ...defaultIgnore ,
465
+ ] ,
466
+ absolute : true ,
467
+ } )
468
+ : [ ] ) ,
469
+ ]
470
+
471
+ if ( files . length === 0 ) {
472
+ // eslint-disable-next-line unicorn/no-useless-undefined
473
+ return undefined
474
+ }
475
+
476
+ return {
477
+ files : new Set ( files . map ( toNativePathSeparator ) ) ,
478
+ mapperFn,
479
+ }
480
+ } )
481
+ . filter ( isDefined )
414
482
415
483
mappersCachedOptions = options
416
484
}
@@ -427,3 +495,46 @@ function mangleScopedPackage(moduleName: string) {
427
495
}
428
496
return moduleName
429
497
}
498
+
499
+ /**
500
+ * Replace path `p` from `from` to `to` separator.
501
+ *
502
+ * @param {string } p Path
503
+ * @param {typeof path.sep } from From separator
504
+ * @param {typeof path.sep } to To separator
505
+ * @returns Path with `to` separator
506
+ */
507
+ function replacePathSeparator (
508
+ p : string ,
509
+ from : typeof path . sep ,
510
+ to : typeof path . sep ,
511
+ ) {
512
+ return from === to ? p : p . replaceAll ( from , to )
513
+ }
514
+
515
+ /**
516
+ * Replace path `p` separator to its native separator.
517
+ *
518
+ * @param {string } p Path
519
+ * @returns Path with native separator
520
+ */
521
+ function toNativePathSeparator ( p : string ) {
522
+ return replacePathSeparator (
523
+ p ,
524
+ path [ process . platform === 'win32' ? 'posix' : 'win32' ] . sep ,
525
+ path [ process . platform === 'win32' ? 'win32' : 'posix' ] . sep ,
526
+ )
527
+ }
528
+
529
+ /**
530
+ * Check if value is defined.
531
+ *
532
+ * Helper function for TypeScript.
533
+ * Should be removed when upgrading to TypeScript >= 5.5.
534
+ *
535
+ * @param {T | null | undefined } value Value
536
+ * @returns `true` if value is defined, `false` otherwise
537
+ */
538
+ function isDefined < T > ( value : T | null | undefined ) : value is T {
539
+ return value !== null && value !== undefined
540
+ }
0 commit comments