Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

depcheck

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

depcheck - npm Package Compare versions

Comparing version 0.3.1 to 0.4.0

test/fake_modules/bad_deep/package.json

224

index.js
var fs = require("fs");
var path = require("path");
var esprima = require("esprima");
var sets = require("simplesets");
var detective = require('detective');
var q = require('q');
var walkdir = require("walkdir");
var _ = require('lodash');
var minimatch = require('minimatch');
if (typeof String.prototype.startsWith !== "function") {
String.prototype.startsWith = function (str) {
return this.slice(0, str.length) === str;
};
}
function traverse(object, visitor) {
var key, child;
if (visitor.call(null, object) === false) {
return;
}
for (key in object) {
if (object.hasOwnProperty(key)) {
child = object[key];
if (typeof child === "object" && child !== null) {
traverse(child, visitor);
}
}
}
}
function isRequire(node) {
return node.callee.name === "require" || (node.callee.property && node.callee.property.name === "loadNpmTasks");
}
function parse(filename) {
function getModulesRequiredFromFilename(filename) {
var content = fs.readFileSync(filename, "utf-8");
var lines;
try {
lines = content.split("\n");
if (lines[0][0] === "#") {
lines.shift();
content = lines.join("\n");
return detective(content, {
word: '',
isRequire: function(node) {
var callee = node.callee;
return callee &&
(
(node.type === 'CallExpression' && callee.type === 'Identifier'
&& callee.name === 'require')
||
(callee.property && callee.property.name === 'loadNpmTasks')
);
}
return esprima.parse(content, {tolerant: true});
} catch (e) {
return null;
}
});
}
function checkFile(filename) {
var used = new sets.Set();
var syntax = parse(filename);
function checkDirectory(dir, ignoreDirs, deps, devDeps) {
if (!syntax) {
return new sets.Set();
}
var deferred = q.defer();
var directoryPromises = [];
var finder = walkdir(dir, { "no_recurse": true });
traverse(syntax, function (node) {
var arg;
if (node.type !== "CallExpression") {
return;
finder.on("directory", function (subdir) {
if (ignoreDirs.contains(path.basename(subdir))
|| (deps.isEmpty() && devDeps.isEmpty())) {
return;
}
if (node.arguments.length !== 1) {
return;
}
if (!isRequire(node)) {
return;
}
arg = node.arguments[0];
directoryPromises.push(checkDirectory(subdir, ignoreDirs, deps, devDeps));
});
if (arg.type === "Literal" && arg.value[0] !== ".") {
used.add(arg.value);
finder.on("file", function (filename) {
if (path.extname(filename) === ".js") {
var modulesRequired = getModulesRequiredFromFilename(filename);
deps = deps.difference(modulesRequired);
devDeps = devDeps.difference(modulesRequired);
}
});
return used;
}
finder.on("end", function () {
deferred.resolve(q.allSettled(directoryPromises).then(function(directoryResults) {
function hasBin(root, dependency) {
try {
var depPkg = require(path.join(root, "node_modules", dependency, "package.json"));
return depPkg.bin !== undefined;
} catch (e) {
return false;
}
}
_(directoryResults).each(function(result) {
if (result.state === 'fulfilled') {
deps = deps.intersection(result.value.dependencies);
devDeps = devDeps.intersection(result.value.devDependencies);
}
});
function collectUnused(root, usedDependencies, definedDependencies) {
var found = new sets.Set();
definedDependencies.array().forEach(function (definedDependency) {
usedDependencies.array().forEach(function (usedDependency) {
if (usedDependency === definedDependency || usedDependency.startsWith(definedDependency + "/") || hasBin(root, definedDependency)) {
found.add(definedDependency);
}
});
return {
dependencies: deps.valueOf(),
devDependencies: devDeps.valueOf()};
}));
});
return definedDependencies.difference(found).array();
return deferred.promise;
}
function check(options, root, files, cb) {
var pkg = require(path.join(root, "/package.json"));
var deps = new sets.Set(Object.keys(pkg.dependencies));
var usedDependencies = new sets.Set();
var ret = {};
function depCheck(rootDir, options, cb) {
files.forEach(function (file) {
usedDependencies = usedDependencies.union(checkFile(file));
});
var pkg = require(path.join(rootDir, 'package.json'));
var deps = filterDependencies(pkg.dependencies);
var devDeps = filterDependencies(options.withoutDev ? [] : pkg.devDependencies);
var ignoreDirs = _([
'.git',
'.svn',
'.hg',
'.idea',
'node_modules'
])
.concat(options.ignoreDirs)
.flatten()
.unique();
ret.dependencies = collectUnused(root, usedDependencies, deps);
function isIgnored(dependency) {
return _.any(options.ignoreMatches, function(match) {
return minimatch(dependency, match);
});
}
if (!options.withoutDev) {
ret.devDependencies = collectUnused(root, usedDependencies, new sets.Set(Object.keys(pkg.devDependencies || {})));
} else {
ret.devDependencies = [];
function hasBin(dependency) {
try {
var depPkg = require(path.join(rootDir, "node_modules", dependency, "package.json"));
return _.has(depPkg, 'bin');
} catch (e) {}
}
cb(ret);
}
function filterDependencies(dependencies) {
return _(dependencies)
.keys()
.reject(hasBin)
.reject(isIgnored)
}
function collectSubdirectories(directories, cb) {
var n = 0;
var files = [];
directories.forEach(function (dir) {
var finder = walkdir(dir);
n++;
finder.on("file", function (file) {
files.push(file);
});
finder.on("end", function () {
n--;
if (n === 0) {
cb(files);
}
});
});
return checkDirectory(rootDir, ignoreDirs, deps, devDeps)
.then(cb)
.done();
}
module.exports = function checkDirectory(dir, options, cb) {
var files = [];
var directories = [];
var finder = walkdir(dir, { "no_recurse": true });
finder.on("directory", function (dir) {
if (path.basename(dir) === "node_modules") {
return;
}
directories.push(dir);
});
finder.on("file", function (file) {
if (path.extname(file) !== ".js") {
return;
}
files.push(file);
});
finder.on("end", function () {
if (directories.length === 0) {
check(options, dir, files, cb);
} else {
collectSubdirectories(directories, function (subFiles) {
check(options, dir, files.concat(subFiles), cb);
});
}
});
};
module.exports = depCheck;
{
"name": "depcheck",
"version": "0.3.1",
"version": "0.4.0",
"description": "Check dependencies in your node module",

@@ -20,11 +20,14 @@ "main": "index",

"dependencies": {
"optimist": "~0.6.0",
"walkdir": "0.0.7",
"detective": "^3.1.0",
"esprima": "~1.0.4",
"simplesets": "~1.2.0"
"lodash": "^2.4.1",
"minimatch": "^0.3.0",
"q": "^1.0.1",
"walkdir": "0.0.7"
},
"devDependencies": {
"should": "~1.2.2",
"mocha": "~1.8.1"
"mocha": "~1.8.1",
"optimist": "~0.6.0"
}
}

@@ -35,3 +35,11 @@ # depcheck [![build status](https://secure.travis-ci.org/rumpl/depcheck.png)](http://travis-ci.org/rumpl/depcheck)

var options = {
"withoutDev": false // Check against devDependencies too
"withoutDev": false, // Check against devDependencies too
"ignoreDirs": [ // Pathnames to ignore
"sandbox",
"dist",
"bower_components"
],
"ignoreMatches": [ // Ignore dependencies that match these minimatch patterns
"grunt-*"
]
};

@@ -38,0 +46,0 @@ var root = path.resolve("some path");

@@ -50,2 +50,21 @@ var assert = require("should");

});
it("should should ignore ignoreDirs", function testUnused(done) {
var absolutePath = path.resolve("test/fake_modules/bad");
depcheck(absolutePath, { "ignoreDirs": ['sandbox'] }, function checked(unused) {
assert.equal(unused.dependencies.length, 1);
done();
});
});
it("should should ignore ignoreMatches", function testUnused(done) {
var absolutePath = path.resolve("test/fake_modules/bad");
depcheck(absolutePath, { "ignoreMatches": ['o*'] }, function checked(unused) {
assert.equal(unused.dependencies.length, 0);
done();
});
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc