Skip to content

Commit

Permalink
fix(tsconfig): respect path mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
jjangga0214 committed Aug 15, 2021
1 parent 1561851 commit 00ce62f
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 6 deletions.
62 changes: 57 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const fs = require('fs');
const cabinet = require('filing-cabinet');
const debug = require('debug')('tree');
const Config = require('./lib/Config');
const { createMatchPath } = require('tsconfig-paths')

/**
* Recursively find all dependencies (avoiding circular) traversing the entire dependency tree
Expand All @@ -25,7 +26,7 @@ const Config = require('./lib/Config');
* @param {Boolean} [options.noTypeDefinitions] For TypeScript imports, whether to resolve to `*.js` instead of `*.d.ts`.
* @return {Object}
*/
module.exports = function(options) {
module.exports = function (options) {
const config = new Config(options);

if (!fs.existsSync(config.filename)) {
Expand Down Expand Up @@ -67,7 +68,7 @@ module.exports = function(options) {
*
* Params are those of module.exports
*/
module.exports.toList = function(options) {
module.exports.toList = function (options) {
options.isListForm = true;

return module.exports(options);
Expand All @@ -81,7 +82,7 @@ module.exports.toList = function(options) {
* @param {Config} config
* @return {Array}
*/
module.exports._getDependencies = function(config) {
module.exports._getDependencies = function (config) {
let dependencies;
const precinctOptions = config.detectiveConfig;
precinctOptions.includeCore = false;
Expand All @@ -97,12 +98,22 @@ module.exports._getDependencies = function(config) {
return [];
}


const tsMatchPath = (() => {
if (config.tsConfig) {
const absoluteBaseUrl = path.join(path.dirname(config.tsConfigPath), config.tsConfig.compilerOptions.baseUrl)
// REF: https://github.com/dividab/tsconfig-paths#creatematchpath
return createMatchPath(absoluteBaseUrl, config.tsConfig.compilerOptions.paths)
}
return (alias) => undefined;
})()

const resolvedDependencies = [];

for (let i = 0, l = dependencies.length; i < l; i++) {
const dep = dependencies[i];

const result = cabinet({
let result = cabinet({
partial: dep,
filename: config.filename,
directory: config.directory,
Expand All @@ -114,6 +125,46 @@ module.exports._getDependencies = function(config) {
noTypeDefinitions: config.noTypeDefinitions
});

// Check if the dep is ts path mapping alias, and if so, update the result.
if (!result) {
result = (() => {
// REF: https://github.com/dividab/tsconfig-paths#creatematchpath
const resolvedTsAliasPath = tsMatchPath(dep) // Get absolute path by ts path mapping. `undefined` if non-existent
if (resolvedTsAliasPath) {
const stat = (() => {
try {
// fs.statSync throws an error if path is non-existent
return fs.statSync(resolvedTsAliasPath)
} catch (error) {
return undefined
}
})()
if (stat) {
if (stat.isDirectory()) {
// When directory is imported, index file is resolved
for (const indexFile of ['index.ts', 'index.tsx', 'index.js', 'index.jsx']) {
const filename = path.join(resolvedTsAliasPath, indexFile)
if (fs.existsSync(filename)) {
return filename
}
}
}
// if the path is complete filename
return resolvedTsAliasPath
} else {
// For cases a file extension is omitted when being imported
for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
const filename = resolvedTsAliasPath + ext
if (fs.existsSync(filename)) {
return filename
}
}
}
}
return undefined
})()
}

if (!result) {
debug('skipping an empty filepath resolution for partial: ' + dep);
config.nonExistent.push(dep);
Expand All @@ -123,6 +174,7 @@ module.exports._getDependencies = function(config) {
const exists = fs.existsSync(result);

if (!exists) {

config.nonExistent.push(dep);
debug('skipping non-empty but non-existent resolution: ' + result + ' for partial: ' + dep);
continue;
Expand Down Expand Up @@ -158,7 +210,7 @@ function traverse(config) {
if (config.filter) {
debug('using filter function to filter out dependencies');
debug('unfiltered number of dependencies: ' + dependencies.length);
dependencies = dependencies.filter(function(filePath) {
dependencies = dependencies.filter(function (filePath) {
return config.filter(filePath, config.filename);
});
debug('filtered number of dependencies: ' + dependencies.length);
Expand Down
5 changes: 4 additions & 1 deletion lib/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ class Config {
if (!this.directory) { throw new Error('directory not given'); }
if (this.filter && typeof this.filter !== 'function') { throw new Error('filter must be a function'); }

// tsConfigPath is needed to calculate absolute baseUrl, which the function `createMatchPath` of the package `tsconfig-paths` requires
this.tsConfigPath = options.tsConfigPath
if ('string' === typeof this.tsConfig) {
debug('preparsing the ts config into an object for performance');
const ts = require('typescript');
const tsParsedConfig = ts.readJsonConfigFile(this.tsConfig, ts.sys.readFile);
const obj = ts.parseJsonSourceFileConfigFileContent(tsParsedConfig, ts.sys, path.dirname(this.tsConfig));
this.tsConfigPath = this.tsConfig
this.tsConfig = obj.raw;
}

Expand All @@ -39,7 +42,7 @@ class Config {
debug('visited: ', this.visited);
}

clone () {
clone() {
return new Config(this);
}
}
Expand Down
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"debug": "^4.3.1",
"filing-cabinet": "^3.0.0",
"precinct": "^8.0.0",
"tsconfig-paths": "^3.10.1",
"typescript": "^3.9.7"
},
"devDependencies": {
Expand Down

0 comments on commit 00ce62f

Please sign in to comment.