bit-bin
Version:
<a href="https://opensource.org/licenses/Apache-2.0"><img alt="apache" src="https://img.shields.io/badge/License-Apache%202.0-blue.svg"></a> <a href="https://github.com/teambit/bit/blob/master/CONTRIBUTING.md"><img alt="prs" src="https://img.shields.io/b
217 lines (178 loc) • 5.31 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.processPath = processPath;
exports.default = generateTree;
function _os() {
const data = _interopRequireDefault(require("os"));
_os = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _dependencyTree() {
const data = _interopRequireDefault(require("./dependency-tree"));
_dependencyTree = function () {
return data;
};
return data;
}
// most of the functions in this file were taken from the Madge project: https://github.com/pahen/madge
// reasons for not using Madge directly: 1) it has issues with TypeScript on Windows. 2) it has issues with tsx files
/**
* Check if running on Windows.
* @type {Boolean}
*/
const isWin = _os().default.platform() === 'win32';
/**
* Check if path is from NPM folder
* @param {String} path
* @return {Boolean}
*/
function isNpmPathFunc(pathStr) {
return pathStr.indexOf('node_modules') >= 0;
}
/**
* Sort tree.
* @param {Object} tree
* @return {Object}
*/
function sort(tree) {
return Object.keys(tree).sort().reduce((acc, id) => {
acc[id] = tree[id].sort();
return acc;
}, {});
}
/**
* Exclude modules from tree using RegExp.
* @param {Object} tree
* @param {Array} excludeRegExp
* @return {Object}
*/
function exclude(tree, excludeRegExp) {
const regExpList = excludeRegExp.map(re => new RegExp(re));
function regExpFilter(id) {
return regExpList.findIndex(regexp => regexp.test(id)) < 0;
}
return Object.keys(tree).filter(regExpFilter).reduce((acc, id) => {
acc[id] = tree[id].filter(regExpFilter);
return acc;
}, {});
}
/**
* Process absolute path and return a shorter one.
* @param {String} absPath
* @param {Object} cache
* @param {String} baseDir
* @return {String}
*/
function processPath(absPath, cache, baseDir) {
if (cache[absPath]) {
return cache[absPath];
}
let relPath = _path().default.relative(baseDir, absPath);
if (isWin) {
relPath = relPath.replace(/\\/g, '/');
}
cache[absPath] = relPath;
return relPath;
}
/**
* Convert deep tree produced by dependency-tree to a
* shallow (one level deep) tree used by madge.
* @param {Object} depTree
* @param {Object} tree
* @param {Object} pathCache
* @param {String} baseDir
* @return {Object}
*/
function convertTreePaths(depTree, pathCache, baseDir) {
const tree = {};
Object.keys(depTree).forEach(file => {
tree[processPath(file, pathCache, baseDir)] = depTree[file].map(d => processPath(d, pathCache, baseDir));
});
return tree;
}
/**
* Generate the tree from the given files
* @param {Array} files
* @param config
* @return {Object}
*/
function generateTree(files = [], config) {
const depTree = {};
const nonExistent = {};
const npmPaths = {};
const pathCache = {};
const pathMap = [];
const errors = {};
files.forEach(file => {
if (depTree[file]) {
return;
}
const detective = config.detectiveOptions;
try {
const dependencyTreeResult = (0, _dependencyTree().default)({
filename: file,
directory: config.baseDir,
requireConfig: config.requireConfig,
webpackConfig: config.webpackConfig,
resolveConfig: config.resolveConfig,
visited: config.visited,
errors,
filter: (dependencyFilePath, traversedFilePath) => {
let dependencyFilterRes = true;
const isNpmPath = isNpmPathFunc(dependencyFilePath);
if (config.dependencyFilter) {
dependencyFilterRes = config.dependencyFilter(dependencyFilePath, traversedFilePath, config.baseDir);
}
if (config.includeNpm && isNpmPath) {
(npmPaths[traversedFilePath] = npmPaths[traversedFilePath] || []).push(dependencyFilePath);
}
return !isNpmPath && (dependencyFilterRes || dependencyFilterRes === undefined);
},
detective,
nonExistent,
pathMap,
cacheProjectAst: config.cacheProjectAst
});
Object.assign(depTree, dependencyTreeResult);
} catch (err) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
errors[file] = err;
}
});
let tree = convertTreePaths(depTree, pathCache, config.baseDir); // rename errors keys from absolute paths to relative paths
Object.keys(errors).forEach(file => {
const relativeFile = processPath(file, pathCache, config.baseDir);
if (relativeFile !== file) {
errors[relativeFile] = errors[file];
delete errors[file];
}
});
Object.keys(npmPaths).forEach(npmKey => {
const id = processPath(npmKey, pathCache, config.baseDir); // a file might not be in the tree if it has errors or errors found with its parents
if (!tree[id]) return;
npmPaths[npmKey].forEach(npmPath => {
tree[id].push(processPath(npmPath, pathCache, config.baseDir));
});
});
if (config.excludeRegExp) {
tree = exclude(tree, config.excludeRegExp);
}
return {
madgeTree: sort(tree),
skipped: nonExistent,
pathMap,
errors
};
}
;