Skip to content
This repository was archived by the owner on Oct 24, 2018. It is now read-only.

Commit 2e243dd

Browse files
committed
First commit
0 parents  commit 2e243dd

File tree

7 files changed

+320
-0
lines changed

7 files changed

+320
-0
lines changed

.editorconfig

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# editorconfig.org
2+
root = true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf
8+
charset = utf-8
9+
trim_trailing_whitespace = true
10+
insert_final_newline = true

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

.jshintrc

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"node": true,
3+
"esnext": true,
4+
"bitwise": true,
5+
"curly": true,
6+
"eqeqeq": true,
7+
"eqnull": true,
8+
"immed": true,
9+
"latedef": true,
10+
"newcap": true,
11+
"noarg": true,
12+
"undef": true,
13+
"strict": false,
14+
"trailing": true,
15+
"smarttabs": true,
16+
"indent": 2,
17+
"white": true
18+
}

README.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# depmissing
2+
3+
Sometimes you could install a dependency an forget to install with `--save`, if it happens, your project will work in your machine but can break in a build or in other machine. `depmissing` helps you find node modules that you are using but is not in `package.json`.
4+
5+
depmissing was made based on [depcheck](https://github.com/rumpl/depcheck).
6+
7+
## Installation
8+
9+
`npm install depmissing -g`
10+
11+
## Usage
12+
13+
`depmissing <directory>`
14+
15+
Where `<directory>` is the root directory of your application (where the package.json is).
16+
17+
### Options
18+
19+
`--ignore` : list of directories that should be ignored.
20+
21+
`--ignoreModules` : list of modules that should be ignored.
22+
23+
### .missingdepsrc
24+
You can also specify the options to `depmissing` into a '.missingdepsrc' file in the root of your project.
25+
26+
```
27+
{
28+
"ignore": ["vendor", "build", "specs", "fixtures"],
29+
"ignoreModules": ["app"]
30+
]
31+
}
32+
```
33+
34+
## License
35+
36+
[MIT](http://rumpl.mit-license.org)

bin/depmissing

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env node
2+
3+
var optimist = require('optimist')
4+
.usage('Usage: $0 [DIRECTORY]')
5+
.boolean('dev')
6+
.default('dev', true)
7+
.describe('no-dev', 'Don\'t look at devDependecies')
8+
.describe('json', 'Output results to JSON');
9+
10+
var argv = optimist.argv;
11+
12+
var checkDirectory = require('../index');
13+
var fs = require('fs');
14+
var path = require('path');
15+
var dir = argv._[0] || '.';
16+
var absolutePath = path.resolve(dir);
17+
var ignoredDir = argv.ignore || '';
18+
var ignoredPackages = argv.ignoreModules || '';
19+
20+
fs.exists(absolutePath, function (pathExists) {
21+
if (pathExists) {
22+
fs.exists(absolutePath + path.sep + 'package.json', function (exists) {
23+
if (exists) {
24+
run();
25+
} else {
26+
console.error('Path ' + dir + ' does not contain a package.json file');
27+
optimist.showHelp();
28+
process.exit(-1);
29+
}
30+
});
31+
} else {
32+
console.error('Path ' + dir + ' does not exist');
33+
process.exit(-1);
34+
}
35+
});
36+
37+
function run() {
38+
checkDirectory(absolutePath, {
39+
"withoutDev": !argv.dev,
40+
"ignoreDirs": ignoredDir.split(','),
41+
"ignorePackages": ignoredPackages.split(',')
42+
}, function (unused) {
43+
44+
if (argv.json) {
45+
console.log(JSON.stringify(unused));
46+
return process.exit(0);
47+
}
48+
49+
if (Object.keys(unused.missing).length === 0) {
50+
console.log('No missing dependencies');
51+
process.exit(0);
52+
} else {
53+
if (Object.keys(unused.missing).length !== 0) {
54+
console.log('Missing Dependencies');
55+
for(var i in unused.missing){
56+
console.log('* '+i+': '+unused.missing[i]);
57+
}
58+
}
59+
process.exit(-1);
60+
}
61+
});
62+
}

index.js

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
var fs = require("fs");
2+
var path = require("path");
3+
var detective = require('detective');
4+
var q = require('q');
5+
var walkdir = require("walkdir");
6+
var _ = require('lodash');
7+
var minimatch = require('minimatch');
8+
var util = require('util');
9+
var fs = require('fs');
10+
var merge = require('merge');
11+
12+
function getModulesRequiredFromFilename(filename) {
13+
var content = fs.readFileSync(filename, "utf-8");
14+
try {
15+
return detective(content, {
16+
word: '',
17+
isRequire: function(node) {
18+
var callee = node.callee;
19+
return callee &&
20+
(
21+
(node.type === 'CallExpression' && callee.type === 'Identifier'
22+
&& callee.name === 'require')
23+
||
24+
(callee.property && callee.property.name === 'loadNpmTasks')
25+
);
26+
}
27+
});
28+
} catch (err) {
29+
return err;
30+
}
31+
}
32+
33+
var missing = [];
34+
function checkDirectory(dir, ignoreDirs, deps, ignorePackages) {
35+
36+
var deferred = q.defer();
37+
var directoryPromises = [];
38+
var finder = walkdir(dir, { "no_recurse": true });
39+
var invalidFiles = {};
40+
41+
finder.on("directory", function (subdir) {
42+
if (_.contains(ignoreDirs, path.basename(subdir))
43+
|| (_.isEmpty(deps))) {
44+
return;
45+
}
46+
47+
directoryPromises.push(checkDirectory(subdir, ignoreDirs, deps, ignorePackages));
48+
});
49+
50+
finder.on("file", function (filename) {
51+
if (path.extname(filename) === ".js") {
52+
var modulesRequired = getModulesRequiredFromFilename(filename);
53+
if (util.isError(modulesRequired)) {
54+
invalidFiles[filename] = modulesRequired;
55+
} else {
56+
modulesRequired = modulesRequired.map(function (module) {
57+
return module.replace ? module.replace(/\/.*$/, '') : module;
58+
});
59+
60+
var toCompare = _.difference(modulesRequired, ignorePackages);
61+
var diff = _.difference(toCompare, deps);
62+
diff.forEach(function(item){
63+
missing[item] = filename;
64+
});
65+
//missing = _.uniq(missing.concat(diff));
66+
//console.log(missing);
67+
//deps = _.difference(modulesRequired, deps);
68+
//devDeps = _.difference(modulesRequired, devDeps);
69+
}
70+
}
71+
});
72+
73+
finder.on("end", function () {
74+
deferred.resolve(q.allSettled(directoryPromises).then(function(directoryResults) {
75+
76+
_.each(directoryResults, function(result) {
77+
if (result.state === 'fulfilled') {
78+
invalidFiles = _.merge(invalidFiles, result.value.invalidFiles, {});
79+
deps = _.intersection(deps, result.value.dependencies);
80+
}
81+
});
82+
83+
return {
84+
missing: missing,
85+
dependencies: deps,
86+
devDependencies: [],
87+
invalidFiles: invalidFiles
88+
};
89+
}));
90+
});
91+
92+
return deferred.promise;
93+
}
94+
95+
function depCheck(rootDir, options, cb) {
96+
97+
var pkg = require(path.join(rootDir, 'package.json'));
98+
99+
var rcPath = path.join(rootDir, '.missingdepsrc');
100+
var rc = (fs.existsSync(rcPath)) ? JSON.parse(fs.readFileSync(rcPath, 'utf-8')) : {};
101+
var deps = Object.keys(merge(pkg.dependencies, pkg.devDependencies));
102+
103+
var ignoreDirs = _([
104+
'.git',
105+
'.svn',
106+
'.hg',
107+
'.idea',
108+
'node_modules',
109+
'bower_components'
110+
])
111+
.concat(options.ignoreDirs)
112+
.concat(rc.ignore)
113+
.flatten()
114+
.unique()
115+
.valueOf();
116+
117+
var ignorePackages = _((rc.ignoreModules) ? rc.ignoreModules : [])
118+
.concat(options.ignorePackages)
119+
.concat([
120+
'.',
121+
'..',
122+
"child_process",
123+
"path",
124+
"os",
125+
"fs",
126+
"dns",
127+
"url",
128+
"querystring",
129+
"events"
130+
])
131+
.flatten()
132+
.unique()
133+
.valueOf();
134+
135+
function isIgnored(dependency) {
136+
return _.any(options.ignoreMatches, function(match) {
137+
return minimatch(dependency, match);
138+
});
139+
}
140+
141+
function hasBin(dependency) {
142+
try {
143+
var depPkg = require(path.join(rootDir, "node_modules", dependency, "package.json"));
144+
return _.has(depPkg, 'bin');
145+
} catch (e) {}
146+
}
147+
148+
function filterDependencies(dependencies) {
149+
return _(dependencies)
150+
.keys()
151+
.reject(hasBin)
152+
.reject(isIgnored)
153+
.valueOf();
154+
}
155+
156+
return checkDirectory(rootDir, ignoreDirs, deps, ignorePackages)
157+
.then(cb)
158+
.done();
159+
}
160+
161+
module.exports = depCheck;

package.json

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name": "depcheck",
3+
"version": "0.4.7",
4+
"description": "Check dependencies in your node module",
5+
"main": "index",
6+
"bin": {
7+
"depcheck": "bin/depcheck"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git://github.com/rumpl/depcheck.git"
12+
},
13+
"scripts": {
14+
"test": "mocha test/index.js"
15+
},
16+
"author": "Djordje Lukic",
17+
"license": "MIT",
18+
"readmeFilename": "README.md",
19+
"dependencies": {
20+
"detective": "^4.0.0",
21+
"lodash": "^3.3.0",
22+
"merge": "^1.2.0",
23+
"minimatch": "^2.0.1",
24+
"optimist": "~0.6.0",
25+
"q": "^1.0.1",
26+
"walkdir": "0.0.7"
27+
},
28+
"devDependencies": {
29+
"mocha": "^2.1.0",
30+
"should": "^5.0.1"
31+
}
32+
}

0 commit comments

Comments
 (0)