Skip to content

Commit

Permalink
Add support to specify the package.json
Browse files Browse the repository at this point in the history
  • Loading branch information
ramasilveyra committed Jan 29, 2017
1 parent 790dd66 commit f456871
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel

### Changed
- [`no-extraneous-dependencies`]: use `read-pkg-up` to simplify finding + loading `package.json` ([#680], thanks [@wtgtybhertgeghgtwtg])
- Add support to specify the package.json [`no-extraneous-dependencies`] ([#685], thanks [@ramasilveyra])

### Fixed
- attempt to fix crash in [`no-mutable-exports`]. ([#660])
Expand Down Expand Up @@ -383,6 +384,7 @@ for info on changes for earlier releases.
[`no-anonymous-default-export`]: ./docs/rules/no-anonymous-default-export.md

[#712]: https://github.com/benmosher/eslint-plugin-import/pull/712
[#685]: https://github.com/benmosher/eslint-plugin-import/pull/685
[#680]: https://github.com/benmosher/eslint-plugin-import/pull/680
[#654]: https://github.com/benmosher/eslint-plugin-import/pull/654
[#639]: https://github.com/benmosher/eslint-plugin-import/pull/639
Expand Down Expand Up @@ -571,3 +573,4 @@ for info on changes for earlier releases.
[@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
[@duncanbeevers]: https://github.com/duncanbeevers
[@giodamelio]: https://github.com/giodamelio
[@ramasilveyra]: https://github.com/ramasilveyra
8 changes: 7 additions & 1 deletion docs/rules/no-extraneous-dependencies.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Forbid the use of extraneous packages

Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies` or `peerDependencies`.
The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything.
The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behaviour can be changed with the rule option `packageDir`.

### Options

Expand All @@ -27,6 +27,12 @@ You can also use an array of globs instead of literal booleans:

When using an array of globs, the setting will be activated if the name of the file being linted matches a single glob in the array.

Also there is one more option called `packageDir`, this option is to specify the path to the folder containing package.json and is relative to the current working directory.

```js
"import/no-extraneous-dependencies": ["error", {"packageDir": './some-dir/'}]
```

## Rule Details

Given the following `package.json`:
Expand Down
28 changes: 23 additions & 5 deletions src/rules/no-extraneous-dependencies.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
import path from 'path'
import fs from 'fs'
import readPkgUp from 'read-pkg-up'
import minimatch from 'minimatch'
import importType from '../core/importType'
import isStaticRequire from '../core/staticRequire'

function getDependencies(context) {
function getDependencies(context, packageDir) {
try {
const pkg = readPkgUp.sync({cwd: context.getFilename(), normalize: false})
if (!pkg || !pkg.pkg) {
const packageContent = packageDir
? JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8'))
: readPkgUp.sync({cwd: context.getFilename(), normalize: false}).pkg

if (!packageContent) {
return null
}
const packageContent = pkg.pkg

return {
dependencies: packageContent.dependencies || {},
devDependencies: packageContent.devDependencies || {},
optionalDependencies: packageContent.optionalDependencies || {},
peerDependencies: packageContent.peerDependencies || {},
}
} catch (e) {
if (packageDir && e.code === 'ENOENT') {
context.report({
message: 'The package.json file could not be found.',
loc: { line: 0, column: 0 },
})
}
if (e.name === 'JSONError' || e instanceof SyntaxError) {
context.report({
message: 'The package.json file could not be parsed: ' + e.message,
loc: { line: 0, column: 0 },
})
}

return null
}
}
Expand Down Expand Up @@ -93,6 +110,7 @@ module.exports = {
'devDependencies': { 'type': ['boolean', 'array'] },
'optionalDependencies': { 'type': ['boolean', 'array'] },
'peerDependencies': { 'type': ['boolean', 'array'] },
'packageDir': { 'type': 'string' },
},
'additionalProperties': false,
},
Expand All @@ -102,7 +120,7 @@ module.exports = {
create: function (context) {
const options = context.options[0] || {}
const filename = context.getFilename()
const deps = getDependencies(context)
const deps = getDependencies(context, options.packageDir)

if (!deps) {
return {}
Expand Down
1 change: 1 addition & 0 deletions tests/files/with-syntax-error/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ "name": "with-syntax-error" }
28 changes: 28 additions & 0 deletions tests/src/rules/no-extraneous-dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ ruleTester.run('no-extraneous-dependencies', rule, {
filename: path.join(process.cwd(), 'foo.spec.js'),
}),
test({ code: 'require(6)' }),
test({
code: 'import "doctrine"',
options: [{packageDir: path.join(__dirname, '../../../')}],
}),
],
invalid: [
test({
Expand Down Expand Up @@ -154,5 +158,29 @@ ruleTester.run('no-extraneous-dependencies', rule, {
message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
}],
}),
test({
code: 'import "not-a-dependency"',
options: [{packageDir: path.join(__dirname, '../../../')}],
errors: [{
ruleId: 'no-extraneous-dependencies',
message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
}],
}),
test({
code: 'import "bar"',
options: [{packageDir: path.join(__dirname, './doesn-exist/')}],
errors: [{
ruleId: 'no-extraneous-dependencies',
message: 'The package.json file could not be found.',
}],
}),
test({
code: 'import foo from "foo"',
options: [{packageDir: path.join(__dirname, '../../files/with-syntax-error')}],
errors: [{
ruleId: 'no-extraneous-dependencies',
message: 'The package.json file could not be parsed: Unexpected token { in JSON at position 1',
}],
}),
],
})

0 comments on commit f456871

Please sign in to comment.