johnny-dependency
Version:
npm -ls for remote packages
60 lines (43 loc) • 1.89 kB
JavaScript
const pacote = require('pacote');
const rxjs = require('rxjs');
const npa = require('npm-package-arg');
const { getPackageMeta } = require('./util');
function flattenDependencies(deps) {
return Object.keys(deps).reduce((acc, name) => {
const version = deps[name];
return acc.concat({ name, version });
}, []);
}
function validateDeps(packages) {
return packages.filter(npmPackage => {
const type = npa(`${npmPackage.name}@${npmPackage.version}`).type;
return type === 'tag' || type === 'version' || type === 'range';
});
}
function getDependencies(thePackage, pacoteOptions = {}) {
const resolvedDependencies = {};
function getPackage(npmPackage) {
const spec = `${npmPackage.name}@${npmPackage.version}`;
return pacote.manifest(spec, pacoteOptions);
}
function getDirectDependencies(npmPackage, manifest) {
const key = `${npmPackage.name}@${npmPackage.version}`;
if (!(key in resolvedDependencies)) {
resolvedDependencies[key] = manifest.version;
const dependencies = validateDeps(flattenDependencies(manifest.dependencies));
return rxjs.Observable.merge(rxjs.Observable.of(getPackageMeta(npmPackage, manifest)), rxjs.Observable.from(dependencies).mergeMap(dependency => getPackage(dependency).then(depManifest => ({ dependency, depManifest }))).mergeMap(({ dependency, depManifest }) => getDirectDependencies(dependency, depManifest)));
}
return rxjs.Observable.empty();
}
function getAllDependencies(npmPackage) {
return new Promise(resolve => {
getPackage(npmPackage).then(manifest => {
getDirectDependencies(npmPackage, manifest).reduce((acc, curr) => acc.concat(curr), []).subscribe(dependencies => {
resolve({ dependencies, resolvedDependencies });
});
});
});
}
return getAllDependencies(thePackage);
}
module.exports = getDependencies;