Skip to content

Commit ad33780

Browse files
committed
add support for multiple tsconfigs
1 parent 18eafa2 commit ad33780

File tree

1 file changed

+76
-29
lines changed

1 file changed

+76
-29
lines changed

Diff for: index.js

+76-29
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ const debug = require('debug');
77

88
const log = debug('eslint-import-resolver-typescript');
99

10+
const extensions = Object.keys(require.extensions).concat(
11+
'.ts',
12+
'.tsx',
13+
'.d.ts',
14+
);
15+
1016
/**
1117
* @param {string} source the module to resolve; i.e './some-module'
1218
* @param {string} file the importing file's full path; i.e. '/usr/local/bin/file.js'
1319
*/
14-
function resolveFile(source, file, config) {
20+
function resolveFile(source, file, options = {}) {
1521
log('looking for:', source);
1622

1723
// don't worry about core node modules
@@ -24,38 +30,16 @@ function resolveFile(source, file, config) {
2430
};
2531
}
2632

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);
5337
}
5438

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
5640
let foundNodePath;
5741
try {
58-
foundNodePath = resolve.sync(foundTsPath || source, {
42+
foundNodePath = resolve.sync(mappedPath || source, {
5943
extensions,
6044
basedir: path.dirname(path.resolve(file)),
6145
packageFilter,
@@ -79,13 +63,76 @@ function resolveFile(source, file, config) {
7963
found: false,
8064
};
8165
}
66+
8267
function packageFilter(pkg) {
8368
if (pkg['jsnext:main']) {
8469
pkg['main'] = pkg['jsnext:main'];
8570
}
8671
return pkg;
8772
}
8873

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+
89136
module.exports = {
90137
interfaceVersion: 2,
91138
resolve: resolveFile,

0 commit comments

Comments
 (0)