Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
find some cycles in typescript imports
const fs = require('fs');
const path = require('path');
const entry = path.resolve(process.argv.slice(2)[0]) || './index.ts';
const entryPath = path.dirname(entry);
/**
* Tries to find all imported file names in given file.
* @param {string} fileName
* @returns {string[]} importedFiles
*/
function findImportsInFile(fileName) {
const fileContents = fs.readFileSync(fileName, 'utf8');
const importedFiles = [];
if (!fileContents) {
return importedFiles;
}
fileContents.split('\n').forEach(l => {
const match = /^import.*from\s+'(.*)'/.exec(l);
if (match === null || !match[1].startsWith('.')) {
return;
}
importPath = path.resolve(path.dirname(fileName), match[1]);
const extensions = ['', '/index.ts', '.ts'];
for (let i = 0; i < extensions.length; i++) {
const ext = extensions[i];
try {
if (fs.statSync(importPath + ext).isFile()) {
importedFiles.push(importPath + ext);
break;
}
} catch (e) {
continue;
}
}
});
return importedFiles;
}
/**
* Looks for cycles in import statements
* Returns a list of cycles found (maybe not complete).
* @param {string} start
* @param {string[]} pathSoFar
* @returns {string[][]} cycles
*/
function searchForCycles(start, pathSoFar = []) {
let cycles = [];
pathSoFar = pathSoFar.concat([start]);
const arr = findImportsInFile(start);
for (let i = 0; i < arr.length; i++) {
const f = arr[i];
if (pathSoFar.indexOf(f) !== -1) {
cycles.push(pathSoFar.slice(pathSoFar.indexOf(f)));
} else {
cycles = cycles.concat(searchForCycles(f, pathSoFar));
}
}
return cycles;
}
const C = searchForCycles(entry);
if (C.length > 0) {
console.error(
C
.map(A => A.map(f => path.relative(entryPath, f)))
.map(A => A.concat([A[0]]).join("--->"))
.reduce((prev, next) => prev.indexOf(next) === -1 ? prev.concat([next]) : prev, [])
.join("\n")
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment