Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
Add resolving of package.json directly from files
Browse files Browse the repository at this point in the history
Making it enough to specify which files to check the dependencies of
  • Loading branch information
voxpelli committed Jul 28, 2019
1 parent 011184c commit da6c139
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 33 deletions.
6 changes: 3 additions & 3 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ if (args.version) {
}

if (args.help || args._.length === 0) {
console.log('\nUsage: dependency-check <path to package.json or module folder> <additional entries to add> <options>')
console.log('\nUsage: dependency-check <path to module files, package.json or module folder> <additional entries to add> <options>')

console.log('\nOptions:')
console.log('--missing (default) Check to make sure that all modules in your code are listed in your package.json')
console.log('--unused, --extra The inverse of the --missing check and will tell you which modules in your package.json *were not* used in your code')
console.log("--no-dev Won't tell you about devDependencies that are missing or unused")
console.log("--no-peer Won't tell you about peerDependencies that are missing or unused")
console.log("--ignore-module, -i Won't tell you about these module names when missing or unused. Supports globbing")
console.log('--entry By default your main and bin entries from package.json will be parsed, but you can add more the list of entries by passing them in as --entry')
console.log("--no-default-entries Won't parse your main and bin entries from package.json")
console.log('--entry If a package.json or module folder was set, then by default the main and bin entries in the package.json will be parsed, but you can add more the list of entries by passing them in as --entry. Supports globbing')
console.log("--no-default-entries Won't parse your main and bin entries from package.json even when a package.json or module folder has been defined")
console.log('--detective Requireable path containing an alternative implementation of the detective module that supports alternate syntaxes')
console.log("--extensions, -e List of file extensions with detective to use when resolving require paths. Eg. 'js,jsx:detective-es6'")
console.log('--version Show current version')
Expand Down
73 changes: 52 additions & 21 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const debug = require('debug')('dependency-check')
const isRelative = require('is-relative')
const globby = require('globby')
const micromatch = require('micromatch')
const pkgUp = require('pkg-up')

const promisedReadPackage = function (pkgPath) {
return new Promise((resolve, reject) => {
Expand All @@ -19,20 +20,62 @@ const promisedReadPackage = function (pkgPath) {
})
}

const resolveGlobbedPath = function (entries, cwd) {
const paths = []

if (typeof entries === 'string') entries = [entries]

debug('globby resolving', entries)

globby.sync(entries, {
cwd,
absolute: true,
expandDirectories: false
}).forEach(entry => {
// Globby yields unix-style paths.
const normalized = path.resolve(entry)

if (paths.indexOf(normalized) === -1) {
paths.push(normalized)
}
})

debug('globby resolved', paths)

return paths
}

module.exports = function (opts, cb) {
let pkgPath = opts.path
let entries

const result = promisedReadPackage(pkgPath)
.catch(err => {
if (err && err.code === 'EISDIR') {
if (!err) {
return Promise.reject(new Error('Failed to read package.json, but received no error'))
} else if (pkgPath.endsWith('/package.json') || pkgPath === 'package.json') {
return Promise.reject(new Error('Failed to read package.json: ' + err.message))
} else if (err.code === 'EISDIR') {
pkgPath = path.join(pkgPath, 'package.json')
return promisedReadPackage(pkgPath)
}
return Promise.reject(err)

// We've likely been given entries rather than a package.json or module path, try resolving that instead
entries = resolveGlobbedPath(pkgPath)

if (!entries[0]) {
return Promise.reject(new Error('Failed to find package.json, could not find any matching files'))
}

opts.noDefaultEntries = true
pkgPath = pkgUp.sync({ cwd: path.dirname(entries[0]) })

return promisedReadPackage(pkgPath)
})
.then(pkg => parse({
path: pkgPath,
package: pkg,
entries: opts.entries,
entries: (entries || []).concat(opts.entries),
noDefaultEntries: opts.noDefaultEntries,
builtins: opts.builtins,
extensions: getExtensions(opts.extensions, opts.detective)
Expand Down Expand Up @@ -146,10 +189,12 @@ function parse (opts) {
const extensions = opts.extensions

const deps = {}
const paths = []
const seen = []
const core = []
const mainPath = path.resolve(pkg.main || path.join(path.dirname(pkgPath), 'index.js'))

let paths = []

if (!opts.noDefaultEntries && fs.existsSync(mainPath)) paths.push(mainPath)

if (!opts.noDefaultEntries && pkg.bin) {
Expand All @@ -165,23 +210,9 @@ function parse (opts) {

// pass in custom additional entries e.g. ['./test.js']
if (opts.entries) {
if (typeof opts.entries === 'string') opts.entries = [opts.entries]

debug('globby resolving', opts.entries)

globby.sync(opts.entries, {
cwd: path.dirname(pkgPath),
absolute: true,
expandDirectories: false
}).forEach(entry => {
// Globby yields unix-style paths.
const normalized = path.resolve(entry)

if (paths.indexOf(normalized) === -1) {
debug('globby resolved', normalized)
paths.push(normalized)
}
})
paths = paths.concat(
resolveGlobbedPath(opts.entries, path.dirname(pkgPath))
)
}

debug('entry paths', paths)
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
"check:dependencies": "node cli.js . && node cli.js . --missing --extra --no-dev -e js:detective-cjs",
"check:node-versions": "installed-check --engine-check --no-version-check",
"lint": "standard",
"test-cli-glob": "node cli.js test/ --entry '**/*.js' --no-default-entries",
"test-cli-simple": "node cli.js test/",
"test-cli": "npm-run-all --parallel test-cli-glob test-cli-simple",
"test-cli:main-as-file": "node cli.js test/index.js",
"test-cli:glob": "node cli.js test/ --entry '**/*.js' --no-default-entries",
"test-cli:simple": "node cli.js test/",
"test-cli": "npm-run-all --parallel test-cli:*",
"test": "npm-run-all lint test-cli check:*"
},
"engines": {
Expand All @@ -27,6 +28,7 @@
"is-relative": "^1.0.0",
"micromatch": "^4.0.2",
"minimist": "^1.2.0",
"pkg-up": "^3.1.0",
"read-package-json": "^2.0.10",
"resolve": "^1.1.7"
},
Expand Down
23 changes: 17 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependency-check `2.x` supports Node.js 0.10 and later (Dev note: published usin

## how it works

`dependency-check` parses your module code starting from the default entry files (e.g. `index.js` or `main` and any `bin` commands defined in package.json) and traverses through all relatively required JS files, ultimately producing a list of non-relative modules
`dependency-check` parses your module code starting from the default entry files (e.g. `index.js` or `main` and any `bin` commands defined in package.json or if specific files has been defined, then those) and traverses through all relatively required JS files, ultimately producing a list of non-relative modules

* **relative** - e.g. `require('./a-relative-file.js')`, if one of these are encountered the required file will be recursively parsed by the `dependency-check` algorithm
* **non-relative** - e.g. `require('a-module')`, if one of these are encountered it will get added to the list of dependencies, but subdependencies of the module will not get recursively parsed
Expand All @@ -28,14 +28,24 @@ the goal of this module is to simply check that all non-relative modules that ge

```
$ npm install dependency-check -g
$ dependency-check <package.json file or module folder path>
$ dependency-check <path to module file(s), package.json or module folder>
# e.g.
$ dependency-check ./package.json
Success! All dependencies used in the code are listed in package.json
$ dependency-check ./package.json --unused
Success! All dependencies in package.json are used in the code
# or with file input instead:
$ dependency-check ./index.js
Success! All dependencies used in the code are listed in package.json
# even with globs and multiple inputs:
$ dependency-check ./test/**/*.js ./lib/*.js
Success! All dependencies used in the code are listed in package.json
```

`dependency-check` exits with code 1 if there are discrepancies, in addition to printing them out
Expand Down Expand Up @@ -64,23 +74,23 @@ ignores a module. This works for both `--unused` and `--missing`. You can specif

### --entry

by default your `main` and `bin` entries from package.json will be parsed, but you can add more the list of entries by passing them in as `--entry`, e.g.:
adds more files to be checked to any of the default ones already added, like `tests.js` to the default ones resolved from package.json:

```
dependency-check package.json --entry tests.js
```

in the above example `tests.js` will get added to the entries that get parsed + checked in addition to the defaults. You can specify as many separate `--entry` arguments as you want
you can specify as many separate `--entry` arguments as you want. `--entry` also supports globbing like `**/*.js` and similar.

you can also instead add additional entries directly after your package definition, like:
you can also instead add additional entries directly after your main path, like:

```
dependency-check package.json tests.js
```

### --no-default-entries

running `dependency-check package.json --no-default-entries --entry tests.js` won't parse any entries other than `tests.js`. None of the entries from your package.json `main` and `bin` will be parsed
running eg. `dependency-check package.json --no-default-entries --entry tests.js` won't add any default entries despite the main path given being one to a package.json or module folder. So only the `tests.js` file will be checked

### --extensions, -e

Expand Down Expand Up @@ -126,3 +136,4 @@ See [grunt-dependency-check](https://github.com/sindresorhus/grunt-dependency-ch

- [detective](https://www.npmjs.org/package/detective) is used for parsing `require()` statements, which means it only does **static requires**. this means you should convert things like `var foo = "bar"; require(foo)` to be static, e.g. `require("bar")`
- you can specify as many entry points as you like with multiple `--entry foo.js` arguments
- use globbing to effectively add all the files you want to check

0 comments on commit da6c139

Please sign in to comment.