@@ -7,11 +7,17 @@ const debug = require('debug');
7
7
8
8
const log = debug ( 'eslint-import-resolver-typescript' ) ;
9
9
10
+ const extensions = Object . keys ( require . extensions ) . concat (
11
+ '.ts' ,
12
+ '.tsx' ,
13
+ '.d.ts' ,
14
+ ) ;
15
+
10
16
/**
11
17
* @param {string } source the module to resolve; i.e './some-module'
12
18
* @param {string } file the importing file's full path; i.e. '/usr/local/bin/file.js'
13
19
*/
14
- function resolveFile ( source , file , config ) {
20
+ function resolveFile ( source , file , options = { } ) {
15
21
log ( 'looking for:' , source ) ;
16
22
17
23
// don't worry about core node modules
@@ -24,38 +30,16 @@ function resolveFile(source, file, config) {
24
30
} ;
25
31
}
26
32
27
- let foundTsPath = null ;
28
- const extensions = Object . keys ( require . extensions ) . concat (
29
- '.ts' ,
30
- '.tsx' ,
31
- '.d.ts' ,
32
- ) ;
33
-
34
- // setup tsconfig-paths
35
- const searchStart = config . directory || process . cwd ( ) ;
36
- const configLoaderResult = tsconfigPaths . loadConfig ( searchStart ) ;
37
- if ( configLoaderResult . resultType === 'success' ) {
38
- const matchPath = tsconfigPaths . createMatchPath (
39
- configLoaderResult . absoluteBaseUrl ,
40
- configLoaderResult . paths ,
41
- ) ;
42
-
43
- // look for files based on setup tsconfig "paths"
44
- foundTsPath = matchPath ( source , undefined , undefined , extensions ) ;
45
-
46
- if ( foundTsPath ) {
47
- log ( 'matched ts path:' , foundTsPath ) ;
48
- }
49
- } else {
50
- log ( 'failed to init tsconfig-paths:' , configLoaderResult . message ) ;
51
- // this can happen if the user has problems with their tsconfig
52
- // or if it's valid, but they don't have baseUrl set
33
+ initMappers ( options ) ;
34
+ const mappedPath = getMappedPath ( source , file ) ;
35
+ if ( mappedPath ) {
36
+ log ( 'matched ts path:' , mappedPath ) ;
53
37
}
54
38
55
- // note that even if we match via tsconfig-paths , we still need to do a final resolve
39
+ // note that even if we map the path , we still need to do a final resolve
56
40
let foundNodePath ;
57
41
try {
58
- foundNodePath = resolve . sync ( foundTsPath || source , {
42
+ foundNodePath = resolve . sync ( mappedPath || source , {
59
43
extensions,
60
44
basedir : path . dirname ( path . resolve ( file ) ) ,
61
45
packageFilter,
@@ -79,13 +63,76 @@ function resolveFile(source, file, config) {
79
63
found : false ,
80
64
} ;
81
65
}
66
+
82
67
function packageFilter ( pkg ) {
83
68
if ( pkg [ 'jsnext:main' ] ) {
84
69
pkg [ 'main' ] = pkg [ 'jsnext:main' ] ;
85
70
}
86
71
return pkg ;
87
72
}
88
73
74
+ /**
75
+ * @param {string } source the module to resolve; i.e './some-module'
76
+ * @param {string } file the importing file's full path; i.e. '/usr/local/bin/file.js'
77
+ * @returns The mapped path of the module or undefined
78
+ */
79
+ function getMappedPath ( source , file ) {
80
+ const paths = mappers
81
+ . map ( mapper => mapper ( source , file ) )
82
+ . filter ( path => ! ! path ) ;
83
+
84
+ if ( paths . length > 1 ) {
85
+ log ( 'found multiple matching ts paths:' , paths ) ;
86
+ }
87
+
88
+ return paths [ 0 ] ;
89
+ }
90
+
91
+ let mappers ;
92
+ function initMappers ( options ) {
93
+ if ( mappers ) {
94
+ return ;
95
+ }
96
+
97
+ const isArrayOfStrings = array =>
98
+ Array . isArray ( array ) && array . every ( o => typeof o === 'string' ) ;
99
+
100
+ const configPaths =
101
+ typeof options . directory === 'string'
102
+ ? [ options . directory ]
103
+ : isArrayOfStrings ( options . directory )
104
+ ? options . directory
105
+ : [ process . cwd ( ) ] ;
106
+
107
+ mappers = configPaths
108
+ . map ( path => tsconfigPaths . loadConfig ( path ) )
109
+ . filter ( configLoaderResult => {
110
+ const success = configLoaderResult . resultType === 'success' ;
111
+ if ( ! success ) {
112
+ // this can happen if the user has problems with their tsconfig
113
+ // or if it's valid, but they don't have baseUrl set
114
+ log ( 'failed to init tsconfig-paths:' , configLoaderResult . message ) ;
115
+ }
116
+ return success ;
117
+ } )
118
+ . map ( configLoaderResult => {
119
+ const matchPath = tsconfigPaths . createMatchPath (
120
+ configLoaderResult . absoluteBaseUrl ,
121
+ configLoaderResult . paths ,
122
+ ) ;
123
+
124
+ return ( source , file ) => {
125
+ // exclude files that are not part of the config base url
126
+ if ( ! file . includes ( configLoaderResult . absoluteBaseUrl ) ) {
127
+ return undefined ;
128
+ }
129
+
130
+ // look for files based on setup tsconfig "paths"
131
+ return matchPath ( source , undefined , undefined , extensions ) ;
132
+ } ;
133
+ } ) ;
134
+ }
135
+
89
136
module . exports = {
90
137
interfaceVersion : 2 ,
91
138
resolve : resolveFile ,
0 commit comments