muttley
Version:
Monitor Unit Test Tool
95 lines • 3.92 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const logger_1 = require("./logger");
/**
* Find file dependancies bases on commonJS require statements.
* It does not load the modules - it regexes the files - hence not guarenteed to be 100% correct
*/
class CommonJsRegexDependencyTree {
constructor() {
this.cache = new Map();
}
/**
*
* @param filepath can be absolute or relative path
* @returns a flattened list of all the dependants
*/
getFlat(filepath) {
let list;
if ((list = this.cache.get(filepath)))
return list;
list = this.getImportsCommonJS(filepath);
list && this.cache.set(filepath, list);
return list;
}
/**
*
* @param filepath absolute or relative file path
* @param depth recursion depth - just for logging indentation
* @returns the full list of dependants for the file.
* Only relative dependants are considered - not NODE_MODULES.
*/
getImportsCommonJS(filepath, depth = 0) {
const indent = ' '.repeat(depth);
const list = [];
const folder = path_1.default.dirname(filepath);
fs_1.default.readFileSync(filepath)
.toString()
.split('\n')
.forEach((line) => {
const imports = line.match(/.*require\((.*)\).*/);
if (imports) {
logger_1.logger.debug('Found require on line', line);
if (imports[1].indexOf("'") >= 0 || imports[1].indexOf('"') >= 0) {
const targetModule = imports[1].replace(/['"]/g, '');
let resolvedPath;
if (targetModule.startsWith('.')) {
resolvedPath = path_1.default.resolve(folder, targetModule);
if (resolvedPath.endsWith('.js') || resolvedPath.endsWith('.json')) {
}
else if (fs_1.default.existsSync(resolvedPath)) {
resolvedPath += '/index.js';
}
else {
resolvedPath += '.js';
}
}
else {
// for now ignore node modules
resolvedPath = targetModule;
// resolvedPath = require.resolve(targetModule);
}
// for native modules resolve just returns the module name
if (resolvedPath !== targetModule) {
list.push(resolvedPath);
// l(filepath, 'imports', targetModule, resolvedPath);
}
}
// else it is dynamically computing target string
}
});
const nextLevel = new Set();
logger_1.logger.info(indent, `File ${filepath} depends on ${list}`);
list.forEach((file) => {
const imports = this.getImportsCommonJS(file, depth + 1); // recurse next level down
if (imports.length) {
logger_1.logger.info(indent, `File ${file} depends on ${imports}`);
imports.forEach(importedFile => {
nextLevel.add(importedFile);
});
}
});
const allDependants = [...list, ...Array.from(nextLevel.keys())];
logger_1.logger.info(indent, `Full dependants for ${filepath} are ${allDependants}`);
return allDependants;
}
}
exports.tree = (() => {
return new CommonJsRegexDependencyTree();
})();
//# sourceMappingURL=dependency.js.map