Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: whitelist option for no-extraneous-dependencies #142

Merged
merged 7 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/light-apples-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-import-x": minor
---

Add new option "whitelist" for rule "no-extraneous-dependencies"
24 changes: 19 additions & 5 deletions docs/rules/no-extraneous-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Modules have to be installed for this rule to work.

## Options

This rule supports the following options:
### Dependency Options

`devDependencies`: If set to `false`, then the rule will show an error when `devDependencies` are imported. Defaults to `true`.
Type imports are ignored by default.
Expand All @@ -34,27 +34,41 @@ You can also use an array of globs instead of literal booleans:

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

### Other Options

#### `includeInternal` & `includeTypes`

There are 2 boolean options to opt into checking extra imports that are normally ignored: `includeInternal`, which enables the checking of internal modules, and `includeTypes`, which enables checking of type imports in TypeScript.

```js
"import-x/no-extraneous-dependencies": ["error", {"includeInternal": true, "includeTypes": true}]
```

Also there is one more option called `packageDir`, this option is to specify the path to the folder containing package.json.
#### `packageDir`

The `packageDir` option is to specify the path to the folder containing package.json.

If provided as a relative path string, will be computed relative to the current working directory at linter execution time. If this is not ideal (does not work with some editor integrations), consider using `__dirname` to provide a path relative to your configuration.

```js
"import-x/no-extraneous-dependencies": ["error", {"packageDir": './some-dir/'}]
"import-x/no-extraneous-dependencies": ["error", {"packageDir": "./some-dir/"}]
// or
"import-x/no-extraneous-dependencies": ["error", {"packageDir": path.join(__dirname, 'some-dir')}]
"import-x/no-extraneous-dependencies": ["error", {"packageDir": path.join(__dirname, "some-dir")}]
```

It may also be an array of multiple paths, to support monorepos or other novel project
folder layouts:

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

#### `whitelist`

The `whitelist` option is an optional string array to specify the names of packages that this rule should ignore.

```js
"import-x/no-extraneous-dependencies": ["error", {"whitelist": ["foo", "bar"]}]
```

## Rule Details
Expand Down
16 changes: 15 additions & 1 deletion src/rules/no-extraneous-dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ function reportIfMissing(
depsOptions: DepsOptions,
node: TSESTree.Node,
name: string,
whitelist: Set<string> | undefined,
) {
// Do not report when importing types unless option is enabled
if (
Expand Down Expand Up @@ -292,6 +293,10 @@ function reportIfMissing(

const packageName = realPackageName || importPackageName

if (whitelist?.has(packageName)) {
return
}

if (declarationStatus.isInDevDeps && !depsOptions.allowDevDeps) {
context.report({
node,
Expand Down Expand Up @@ -342,6 +347,7 @@ type Options = {
bundledDependencies?: boolean
includeInternal?: boolean
includeTypes?: boolean
whitelist?: string[]
}

type MessageId =
Expand Down Expand Up @@ -370,6 +376,7 @@ export = createRule<[Options?], MessageId>({
packageDir: { type: ['string', 'array'] },
includeInternal: { type: ['boolean'] },
includeTypes: { type: ['boolean'] },
whitelist: { type: ['array'] },
},
additionalProperties: false,
},
Expand Down Expand Up @@ -408,7 +415,14 @@ export = createRule<[Options?], MessageId>({
return {
...moduleVisitor(
(source, node) => {
reportIfMissing(context, deps, depsOptions, node, source.value)
reportIfMissing(
context,
deps,
depsOptions,
node,
source.value,
options.whitelist ? new Set(options.whitelist) : undefined,
)
},
{ commonjs: true },
),
Expand Down
8 changes: 8 additions & 0 deletions test/rules/no-extraneous-dependencies.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ ruleTester.run('no-extraneous-dependencies', rule, {
},
},
}),

test({
code: 'import "not-a-dependency"',
filename: path.join(packageDirMonoRepoRoot, 'foo.js'),
options: [
{ packageDir: packageDirMonoRepoRoot, whitelist: ['not-a-dependency'] },
],
}),
],
invalid: [
test({
Expand Down
Loading