Skip to content

Instantly share code, notes, and snippets.

@w-vi
Created October 10, 2018 06:56
Show Gist options
  • Save w-vi/b9b25fcd0d5ff8d9ea6df4bf90138c1a to your computer and use it in GitHub Desktop.
Save w-vi/b9b25fcd0d5ff8d9ea6df4bf90138c1a to your computer and use it in GitHub Desktop.
libnpm usage to inspect the dependency tree
'use strict';
const fs = require('fs');
const pkg = require('./package');
const _ = require('lodash');
const npm = require('libnpm');
const async = require('neo-async');
const kv = require('./kv');
function check (pkgjson) => {
let cache = kv();
let queue = [];
const pkgJSON = JSON.parse(fs.readFileSync(pkgjson));
_.each(pkgJSON.dependencies, (v, d) => {
queue.push(`${d}@${v}`);
});
console.log(`Direct dependecies for ${pkgJSON.name}: ${queue.length}`);
let count = 0;
async.whilst (
() => {return (queue.length > 0 || count > 0);},
(cb) => {
let dep = queue.pop();
console.log(`Retrieve manifest for package, pkgversion=${dep}`);
npm.manifest(dep).then(m => {
const pkgid = pkg.getID(m);
console.log(`Inspect package, pkg=${pkgid}`);
if (!cache.get(pkgid)) {
count++;
pkg.inspect(m, (err, pkginfo) => {
if (err) {
console.error(err);
} else {
cache.push(pkginfo.id, pkginfo);
_.each(pkginfo.dependencies, (v, d) => {
queue.push(`${d}@${v}`);
});
}
count--;
return cb();
});
} else {
console.log(`Package found in cache, pkg=${pkgid}`);
return cb();
}
});
},
(err) => {console.log(`Cache stats, size=${cache.size()}, hits=${cache.hits()}, misses=${cache.misses()}`)});
};
'use strict';
function KV (debug=false) {
const kv = {debug: debug};
const store = {};
let hits = 0;
let misses = 0;
let size = 0;
kv.push = function(k, v) {
if (debug) console.log(`KV push, key=${k}, value=${JSON.stringify(v)}`);
const o = store[k];
size++;
store[k] = v;
return o;
};
kv.pop = function(k) {
if (debug) console.log(`KV pop, key=${k}`);
const o = store[k];
size--;
delete store[k];
return o;
};
kv.clear = function() {
if (debug) console.log(`KV clear, size=${size}, hitcount=${hits}, misscount=${misses}`);
for (let k in store) {
delete store[k];
}
size = 0;
hits = 0;
misses = 0;
};
kv.get = function(k) {
const v = store[k];
if (typeof v != "undefined") {
if (debug) console.log(`KV hit, key=${k}`);
hits++;
} else {
if (debug) console.log(`KV miss, key=${k}`);
misses++;
}
return v;
};
kv.size = function() {
return size;
};
kv.hits = function() {
return hits;
};
kv.misses = function() {
return misses;
};
kv.keys = function() {
return Object.keys(store);
};
return kv;
}
module.exports = KV;
'use strict';
const path = require('path');
const fs = require('fs');
const os = require('os');
const npm = require('libnpm');
const _ = require('lodash');
const rmf = require('rimraf');
// tmpdir work kdir
const DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'depc-'));
const LICENSE_FILEPATTERNS = [
/^LICENSE$/,
/^LICENSE.*$/, // e.g. LICENSE.md or LICENSE.txt
/^LICENSE\-\w+$/, // e.g. LICENSE-MIT
/^\w+LICENSE.*$/, // MIT-LICENSE.txt or MIT_LICENSE
/^LICENCE$/,
/^LICENCE.*$/,
/^LICENCE\-\w+$/, // e.g. LICENCE-MIT
/^\w+LICENCE.*$/,
/^COPYING$/,
/^README$/,
];
function getID(manifest) {
return `${manifest.name}-${manifest.version}`;
}
function inspect(manifest, cb) {
const pkgid = getID(manifest);
const dir = path.join(DIR, pkgid);
npm.extract(manifest._id, dir).then(() => {
// check the package.json for the license info
const pkginfo = _.omit(
JSON.parse(fs.readFileSync(path.join(dir, 'package.json'))),
['_resolved', '_integrity', '_from']);
pkginfo.id = pkgid;
fs.readdir(dir, (err, files) => {
if (err) return cb(err);
// collect possible license files in probability order defined by
// LICENSE_FILEPATTERNS
const licenseFiles = _.filter(files, (f) => {
return _.find(LICENSE_FILEPATTERNS, (pat) => {
return pat.test(path.basename(f, path.extname(f)).toUpperCase());
});
});
return cb(null, pkginfo);
});
});
};
function clean(cb) { rmf(DIR, cb); }
module.exports = {inspect, clean, getID};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment