Last active
September 12, 2019 16:00
-
-
Save morulus/3c8bc7a424304fe6be64bf5f7a4a3485 to your computer and use it in GitHub Desktop.
Sort npm packages according to their dependencies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Under MIT License, Vladimir Kalmykov 2019 */ | |
// I'm not sure this is the best solution, but it works and finds cyclical dependencies | |
// Any suggestions? Leave comments. | |
/** | |
* @param packages Array of package.json | |
* @return Array of names | |
*/ | |
function sortAccordingToDepends(packages) { | |
const names = packages.map(pkg => pkg.name); | |
const result = []; | |
let iterationCount = 0; | |
const handlePackage = (pkg, parents = []) => { | |
if (parents.includes(pkg.name)) { | |
console.warn(`Circular dependency detected in the package "${pkg.name}" derived by "${parents.join("\" > \"")}"`); | |
result.push(pkg.name); | |
return; | |
} | |
if (!result.includes(pkg.name)) { | |
const keys = Object.keys(pkg.dependencies || {}); | |
if (keys.length > 0) { | |
const left = keys.filter(name => names.includes(name) && !result.includes(name)); | |
if (left.length === 0) { | |
result.push(pkg.name); | |
} else { | |
left.forEach(leftName => handlePackage( | |
packages.find(p => p.name === leftName), | |
parents.concat([ pkg.name ]) | |
)); | |
} | |
} else { | |
result.push(pkg.name); | |
} | |
} | |
}; | |
while (result.length < packages.length) { | |
if (iterationCount === 100) { | |
/* Find circular dependencies */ | |
const leftPackages = packages | |
.map(pkg => pkg.name) | |
.filter(name => !result.includes(name)); | |
throw new Error(`Circular dependency detected in packages ${leftPackages.join(", ")}`); | |
} | |
iterationCount++; | |
for (let i = 0; i < packages.length; i++) { | |
handlePackage(packages[i]); | |
} | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment