Skip to content

Commit 0fb592e

Browse files
ramasilveyrabenmosher
authored andcommitted
Add support to specify the package.json (#685)
1 parent 2cc9768 commit 0fb592e

File tree

5 files changed

+72
-7
lines changed

5 files changed

+72
-7
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
1111

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

1516
### Fixed
1617
- attempt to fix crash in [`no-mutable-exports`]. ([#660])
@@ -386,6 +387,7 @@ for info on changes for earlier releases.
386387

387388
[#742]: https://github.com/benmosher/eslint-plugin-import/pull/742
388389
[#712]: https://github.com/benmosher/eslint-plugin-import/pull/712
390+
[#685]: https://github.com/benmosher/eslint-plugin-import/pull/685
389391
[#680]: https://github.com/benmosher/eslint-plugin-import/pull/680
390392
[#654]: https://github.com/benmosher/eslint-plugin-import/pull/654
391393
[#639]: https://github.com/benmosher/eslint-plugin-import/pull/639
@@ -575,3 +577,4 @@ for info on changes for earlier releases.
575577
[@duncanbeevers]: https://github.com/duncanbeevers
576578
[@giodamelio]: https://github.com/giodamelio
577579
[@ntdb]: https://github.com/ntdb
580+
[@ramasilveyra]: https://github.com/ramasilveyra

docs/rules/no-extraneous-dependencies.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Forbid the use of extraneous packages
22

33
Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies` or `peerDependencies`.
4-
The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything.
4+
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`.
55

66
### Options
77

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

2828
When using an array of globs, the setting will be set to `true` (no errors reported) if the name of the file being linted matches a single glob in the array, and `false` otherwise.
2929

30+
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.
31+
32+
```js
33+
"import/no-extraneous-dependencies": ["error", {"packageDir": './some-dir/'}]
34+
```
35+
3036
## Rule Details
3137

3238
Given the following `package.json`:

src/rules/no-extraneous-dependencies.js

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,40 @@
11
import path from 'path'
2+
import fs from 'fs'
23
import readPkgUp from 'read-pkg-up'
34
import minimatch from 'minimatch'
45
import importType from '../core/importType'
56
import isStaticRequire from '../core/staticRequire'
67

7-
function getDependencies(context) {
8+
function getDependencies(context, packageDir) {
89
try {
9-
const pkg = readPkgUp.sync({cwd: context.getFilename(), normalize: false})
10-
if (!pkg || !pkg.pkg) {
10+
const packageContent = packageDir
11+
? JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8'))
12+
: readPkgUp.sync({cwd: context.getFilename(), normalize: false}).pkg
13+
14+
if (!packageContent) {
1115
return null
1216
}
13-
const packageContent = pkg.pkg
17+
1418
return {
1519
dependencies: packageContent.dependencies || {},
1620
devDependencies: packageContent.devDependencies || {},
1721
optionalDependencies: packageContent.optionalDependencies || {},
1822
peerDependencies: packageContent.peerDependencies || {},
1923
}
2024
} catch (e) {
25+
if (packageDir && e.code === 'ENOENT') {
26+
context.report({
27+
message: 'The package.json file could not be found.',
28+
loc: { line: 0, column: 0 },
29+
})
30+
}
31+
if (e.name === 'JSONError' || e instanceof SyntaxError) {
32+
context.report({
33+
message: 'The package.json file could not be parsed: ' + e.message,
34+
loc: { line: 0, column: 0 },
35+
})
36+
}
37+
2138
return null
2239
}
2340
}
@@ -93,6 +110,7 @@ module.exports = {
93110
'devDependencies': { 'type': ['boolean', 'array'] },
94111
'optionalDependencies': { 'type': ['boolean', 'array'] },
95112
'peerDependencies': { 'type': ['boolean', 'array'] },
113+
'packageDir': { 'type': 'string' },
96114
},
97115
'additionalProperties': false,
98116
},
@@ -102,7 +120,7 @@ module.exports = {
102120
create: function (context) {
103121
const options = context.options[0] || {}
104122
const filename = context.getFilename()
105-
const deps = getDependencies(context)
123+
const deps = getDependencies(context, options.packageDir)
106124

107125
if (!deps) {
108126
return {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{ "name": "with-syntax-error" }

tests/src/rules/no-extraneous-dependencies.js

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import { test } from '../utils'
22
import * as path from 'path'
3+
import * as fs from 'fs'
34

45
import { RuleTester } from 'eslint'
5-
66
const ruleTester = new RuleTester()
77
, rule = require('rules/no-extraneous-dependencies')
88

9+
const packageDirWithSyntaxError = path.join(__dirname, '../../files/with-syntax-error')
10+
const packageFileWithSyntaxErrorMessage = (() => {
11+
try {
12+
JSON.parse(fs.readFileSync(path.join(packageDirWithSyntaxError, 'package.json')))
13+
} catch (error) {
14+
return error.message
15+
}
16+
})()
17+
918
ruleTester.run('no-extraneous-dependencies', rule, {
1019
valid: [
1120
test({ code: 'import "lodash.cond"'}),
@@ -56,6 +65,10 @@ ruleTester.run('no-extraneous-dependencies', rule, {
5665
filename: path.join(process.cwd(), 'foo.spec.js'),
5766
}),
5867
test({ code: 'require(6)' }),
68+
test({
69+
code: 'import "doctrine"',
70+
options: [{packageDir: path.join(__dirname, '../../../')}],
71+
}),
5972
],
6073
invalid: [
6174
test({
@@ -154,5 +167,29 @@ ruleTester.run('no-extraneous-dependencies', rule, {
154167
message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
155168
}],
156169
}),
170+
test({
171+
code: 'import "not-a-dependency"',
172+
options: [{packageDir: path.join(__dirname, '../../../')}],
173+
errors: [{
174+
ruleId: 'no-extraneous-dependencies',
175+
message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
176+
}],
177+
}),
178+
test({
179+
code: 'import "bar"',
180+
options: [{packageDir: path.join(__dirname, './doesn-exist/')}],
181+
errors: [{
182+
ruleId: 'no-extraneous-dependencies',
183+
message: 'The package.json file could not be found.',
184+
}],
185+
}),
186+
test({
187+
code: 'import foo from "foo"',
188+
options: [{packageDir: packageDirWithSyntaxError}],
189+
errors: [{
190+
ruleId: 'no-extraneous-dependencies',
191+
message: 'The package.json file could not be parsed: ' + packageFileWithSyntaxErrorMessage,
192+
}],
193+
}),
157194
],
158195
})

0 commit comments

Comments
 (0)