From 505fbf4b35c14332bffb0c838cce4843a00fad68 Mon Sep 17 00:00:00 2001 From: Tanuj Kanti <86398394+Tanujkanti4441@users.noreply.github.com> Date: Mon, 29 Jan 2024 23:55:35 +0530 Subject: [PATCH] docs: update `no-restricted-imports` rule (#18015) * docs: update no-restricted-imports rule * fix linting errors * docs: update docs language * fix linting error * remove nodejs import section --- docs/src/rules/no-restricted-imports.md | 418 +++++++++++++++--------- 1 file changed, 257 insertions(+), 161 deletions(-) diff --git a/docs/src/rules/no-restricted-imports.md b/docs/src/rules/no-restricted-imports.md index 81f7ad4a6f9..2ce0d8f9d1a 100644 --- a/docs/src/rules/no-restricted-imports.md +++ b/docs/src/rules/no-restricted-imports.md @@ -20,176 +20,139 @@ It applies to static imports only, not dynamic ones. ## Options -The syntax to specify restricted imports looks like this: +This rule has both string and object options to specify the imported modules to restrict. + +Using string option, you can specify the name of a module that you want to restrict from being imported as a value in the rule options array: ```json "no-restricted-imports": ["error", "import1", "import2"] ``` -or like this: +Examples of **incorrect** code for string option: -```json -"no-restricted-imports": ["error", { "paths": ["import1", "import2"] }] -``` +::: incorrect { "sourceType": "module" } -When using the object form, you can also specify an array of gitignore-style patterns: +```js +/*eslint no-restricted-imports: ["error", "fs"]*/ -```json -"no-restricted-imports": ["error", { - "paths": ["import1", "import2"], - "patterns": ["import1/private/*", "import2/*", "!import2/good"] -}] +import fs from 'fs'; ``` -You may also specify a custom message for any paths you want to restrict as follows: +::: -```json -"no-restricted-imports": ["error", { - "name": "import-foo", - "message": "Please use import-bar instead." -}, { - "name": "import-baz", - "message": "Please use import-quux instead." -}] -``` +String options also restrict the module from being exported, as in this example: -or like this: +::: incorrect { "sourceType": "module" } -```json -"no-restricted-imports": ["error", { - "paths": [{ - "name": "import-foo", - "message": "Please use import-bar instead." - }, { - "name": "import-baz", - "message": "Please use import-quux instead." - }] -}] +```js +/*eslint no-restricted-imports: ["error", "fs"]*/ + +export { fs } from 'fs'; ``` -or like this if you need to restrict only certain imports from a module: +::: -```json -"no-restricted-imports": ["error", { - "paths": [{ - "name": "import-foo", - "importNames": ["Bar"], - "message": "Please use Bar from /import-bar/baz/ instead." - }] -}] -``` +::: incorrect { "sourceType": "module" } -or like this if you want to apply a custom message to pattern matches: +```js +/*eslint no-restricted-imports: ["error", "fs"]*/ -```json -"no-restricted-imports": ["error", { - "patterns": [{ - "group": ["import1/private/*"], - "message": "usage of import1 private modules not allowed." - }, { - "group": ["import2/*", "!import2/good"], - "message": "import2 is deprecated, except the modules in import2/good." - }] -}] +export * from 'fs'; ``` -The custom message will be appended to the default error message. +::: -Pattern matches can also be configured to be case-sensitive: +Examples of **correct** code for string option: -```json -"no-restricted-imports": ["error", { - "patterns": [{ - "group": ["import1/private/prefix[A-Z]*"], - "caseSensitive": true - }] -}] -``` +::: correct { "sourceType": "module" } -Pattern matches can restrict specific import names only, similar to the `paths` option: +```js +/*eslint no-restricted-imports: ["error", "fs"]*/ -```json -"no-restricted-imports": ["error", { - "patterns": [{ - "group": ["utils/*"], - "importNames": ["isEmpty"], - "message": "Use 'isEmpty' from lodash instead." - }] -}] +import crypto from 'crypto'; +export { foo } from "bar"; ``` -Regex patterns can also be used to restrict specific import Name: +::: + +You may also specify a custom message for a particular module using the `name` and `message` properties inside an object, where the value of the `name` is the name of the module and `message` property contains the custom message. (The custom message is appended to the default error message from the rule.) ```json "no-restricted-imports": ["error", { - "patterns": [{ - "group": ["import-foo/*"], - "importNamePattern": "^foo", - }] + "name": "import-foo", + "message": "Please use import-bar instead." +}, { + "name": "import-baz", + "message": "Please use import-quux instead." }] ``` -To restrict the use of all Node.js core imports (via ): - -```json - "no-restricted-imports": ["error", - "assert","buffer","child_process","cluster","crypto","dgram","dns","domain","events","freelist","fs","http","https","module","net","os","path","punycode","querystring","readline","repl","smalloc","stream","string_decoder","sys","timers","tls","tracing","tty","url","util","vm","zlib" - ], -``` - -## Examples - -Examples of **incorrect** code for this rule: +Examples of **incorrect** code for string option: ::: incorrect { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", "fs"]*/ +/*eslint no-restricted-imports: ["error", { + "name": "disallowed-import", + "message": "Please use 'allowed-import' instead" +}]*/ -import fs from 'fs'; +import foo from 'disallowed-import'; ``` ::: -::: incorrect { "sourceType": "module" } +### paths -```js -/*eslint no-restricted-imports: ["error", "fs"]*/ +This is an object option whose value is an array containing the names of the modules you want to restrict. -export { fs } from 'fs'; +```json +"no-restricted-imports": ["error", { "paths": ["import1", "import2"] }] ``` -::: +Examples of **incorrect** code for `paths`: ::: incorrect { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", "fs"]*/ +/*eslint no-restricted-imports: ["error", { "paths": ["cluster"] }]*/ -export * from 'fs'; +import cluster from 'cluster'; ``` ::: -::: incorrect { "sourceType": "module" } +Custom messages for a particular module can also be specified in `paths` array using objects with `name` and `message`. -```js -/*eslint no-restricted-imports: ["error", { "paths": ["cluster"] }]*/ - -import cluster from 'cluster'; +```json +"no-restricted-imports": ["error", { + "paths": [{ + "name": "import-foo", + "message": "Please use import-bar instead." + }, { + "name": "import-baz", + "message": "Please use import-quux instead." + }] +}] ``` -::: +#### importNames -::: incorrect { "sourceType": "module" } +This option in `paths` is an array and can be used to specify the names of certain bindings exported from a module. Import names specified inside `paths` array affect the module specified in the `name` property of corresponding object, so it is required to specify the `name` property first when you are using `importNames` or `message` option. -```js -/*eslint no-restricted-imports: ["error", { "patterns": ["lodash/*"] }]*/ +Specifying `"default"` string inside the `importNames` array will restrict the default export from being imported. -import pick from 'lodash/pick'; +```json +"no-restricted-imports": ["error", { + "paths": [{ + "name": "import-foo", + "importNames": ["Bar"], + "message": "Please use Bar from /import-bar/baz/ instead." + }] +}] ``` -::: +Examples of **incorrect** code when `importNames` in `paths` has `"default"`: ::: incorrect { "sourceType": "module" } @@ -205,6 +168,8 @@ import DisallowedObject from "foo"; ::: +Examples of **incorrect** code for `importNames` in `paths`: + ::: incorrect { "sourceType": "module" } ```js @@ -237,56 +202,54 @@ import * as Foo from "foo"; ::: -::: incorrect { "sourceType": "module" } +Examples of **correct** code for `importNames` in `paths`: + +If the local name assigned to a default export is the same as a string in `importNames`, this will not cause an error. + +::: correct { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { patterns: [{ - group: ["lodash/*"], - message: "Please use the default import from 'lodash' instead." -}]}]*/ +/*eslint no-restricted-imports: ["error", { paths: [{ name: "foo", importNames: ["DisallowedObject"] }] }]*/ -import pick from 'lodash/pick'; +import DisallowedObject from "foo" ``` ::: -::: incorrect { "sourceType": "module" } +::: correct { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { patterns: [{ - group: ["foo[A-Z]*"], - caseSensitive: true +/*eslint no-restricted-imports: ["error", { paths: [{ + name: "foo", + importNames: ["DisallowedObject"], + message: "Please import 'DisallowedObject' from '/bar/baz/' instead." }]}]*/ -import pick from 'fooBar'; +import { AllowedObject as DisallowedObject } from "foo"; ``` ::: -::: incorrect { "sourceType": "module" } +### patterns -```js -/*eslint no-restricted-imports: ["error", { patterns: [{ - group: ["utils/*"], - importNames: ['isEmpty'], - message: "Use 'isEmpty' from lodash instead." -}]}]*/ +This is also an object option whose value is an array. This option allows you to specify multiple modules to restrict using `gitignore`-style patterns. -import { isEmpty } from 'utils/collection-utils'; +Because the patterns follow the `gitignore`-style, if you want to reinclude any particular module this can be done by prefixing a negation (`!`) mark in front of the pattern. (Negated patterns should come last in the array because order is important.) + +```json +"no-restricted-imports": ["error", { + "patterns": ["import1/private/*", "import2/*", "!import2/good"] +}] ``` -::: +Examples of **incorrect** code for `pattern` option: ::: incorrect { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { patterns: [{ - group: ["utils/*"], - importNamePattern: '^is', - message: "Use 'is*' functions from lodash instead." -}]}]*/ +/*eslint no-restricted-imports: ["error", { "patterns": ["lodash/*"] }]*/ -import { isEmpty } from 'utils/collection-utils'; +import pick from 'lodash/pick'; ``` ::: @@ -294,13 +257,9 @@ import { isEmpty } from 'utils/collection-utils'; ::: incorrect { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { patterns: [{ - group: ["foo/*"], - importNamePattern: '^(is|has)', - message: "Use 'is*' and 'has*' functions from baz/bar instead" -}]}]*/ +/*eslint no-restricted-imports: ["error", { "patterns": ["lodash/*", "!lodash/pick"] }]*/ -import { isSomething, hasSomething } from 'foo/bar'; +import pick from 'lodash/map'; ``` ::: @@ -308,26 +267,23 @@ import { isSomething, hasSomething } from 'foo/bar'; ::: incorrect { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { patterns: [{ - group: ["foo/*"], - importNames: ["bar"], - importNamePattern: '^baz', -}]}]*/ +/*eslint no-restricted-imports: ["error", { "patterns": ["import1/*", "!import1/private/*"] }]*/ -import { bar, bazQux } from 'foo/quux'; +import pick from 'import1/private/someModule'; ``` ::: -Examples of **correct** code for this rule: +In this example, `"!import1/private/*"` is not reincluding the modules inside `private` because the negation mark (`!`) does not reinclude the files if it's parent directory is excluded by a pattern. In this case, `import1/private` directory is already excluded by the `import1/*` pattern. (The excluded directory can be reincluded using `"!import1/private"`.) + +Examples of **correct** code for `pattern` option: ::: correct { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", "fs"]*/ +/*eslint no-restricted-imports: ["error", { "patterns": ["crypto/*"] }]*/ import crypto from 'crypto'; -export { foo } from "bar"; ``` ::: @@ -335,11 +291,9 @@ export { foo } from "bar"; ::: correct { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { "paths": ["fs"], "patterns": ["eslint/*"] }]*/ +/*eslint no-restricted-imports: ["error", { "patterns": ["lodash/*", "!lodash/pick"] }]*/ -import crypto from 'crypto'; -import eslint from 'eslint'; -export * from "path"; +import pick from 'lodash/pick'; ``` ::: @@ -347,27 +301,48 @@ export * from "path"; ::: correct { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { paths: [{ name: "foo", importNames: ["DisallowedObject"] }] }]*/ +/*eslint no-restricted-imports: ["error", { "patterns": ["import1/*", "!import1/private"] }]*/ -import DisallowedObject from "foo" +import pick from 'import1/private/someModule'; ``` ::: -::: correct { "sourceType": "module" } +#### group + +The `patterns` array can also include objects. The `group` property is used to specify the `gitignore`-style patterns for restricting modules and the `message` property is used to specify a custom message. + +The `group` property is required property when using objects inside the `patterns` array. + +```json +"no-restricted-imports": ["error", { + "patterns": [{ + "group": ["import1/private/*"], + "message": "usage of import1 private modules not allowed." + }, { + "group": ["import2/*", "!import2/good"], + "message": "import2 is deprecated, except the modules in import2/good." + }] +}] +``` + +Examples of **incorrect** code for `group` option: + +::: incorrect { "sourceType": "module" } ```js -/*eslint no-restricted-imports: ["error", { paths: [{ - name: "foo", - importNames: ["DisallowedObject"], - message: "Please import 'DisallowedObject' from '/bar/baz/' instead." +/*eslint no-restricted-imports: ["error", { patterns: [{ + group: ["lodash/*"], + message: "Please use the default import from 'lodash' instead." }]}]*/ -import { AllowedObject as DisallowedObject } from "foo"; +import pick from 'lodash/pick'; ``` ::: +Examples of **correct** code for this `group` option: + ::: correct { "sourceType": "module" } ```js @@ -381,6 +356,36 @@ import lodash from 'lodash'; ::: +#### caseSensitive + +This is a boolean option and sets the patterns specified in the `group` array to be case-sensitive when `true`. Default is `false`. + +```json +"no-restricted-imports": ["error", { + "patterns": [{ + "group": ["import1/private/prefix[A-Z]*"], + "caseSensitive": true + }] +}] +``` + +Examples of **incorrect** code for `caseSensitive: true` option: + +::: incorrect { "sourceType": "module" } + +```js +/*eslint no-restricted-imports: ["error", { patterns: [{ + group: ["foo[A-Z]*"], + caseSensitive: true +}]}]*/ + +import pick from 'fooBar'; +``` + +::: + +Examples of **correct** code for `caseSensitive: true` option: + ::: correct { "sourceType": "module" } ```js @@ -394,6 +399,38 @@ import pick from 'food'; ::: +#### importNames + +You can also specify `importNames` on objects inside of `patterns`. In this case, the specified names are applied only to the specified `group`. + +```json +"no-restricted-imports": ["error", { + "patterns": [{ + "group": ["utils/*"], + "importNames": ["isEmpty"], + "message": "Use 'isEmpty' from lodash instead." + }] +}] +``` + +Examples of **incorrect** code for `importNames` in `patterns`: + +::: incorrect { "sourceType": "module" } + +```js +/*eslint no-restricted-imports: ["error", { patterns: [{ + group: ["utils/*"], + importNames: ['isEmpty'], + message: "Use 'isEmpty' from lodash instead." +}]}]*/ + +import { isEmpty } from 'utils/collection-utils'; +``` + +::: + +Examples of **correct** code for `importNames` in `patterns`: + ::: correct { "sourceType": "module" } ```js @@ -408,6 +445,65 @@ import { hasValues } from 'utils/collection-utils'; ::: +#### importNamePattern + +This option allows you to use regex patterns to restrict import names: + +```json +"no-restricted-imports": ["error", { + "patterns": [{ + "group": ["import-foo/*"], + "importNamePattern": "^foo", + }] +}] +``` + +Examples of **incorrect** code for `importNamePattern` option: + +::: incorrect { "sourceType": "module" } + +```js +/*eslint no-restricted-imports: ["error", { patterns: [{ + group: ["utils/*"], + importNamePattern: '^is', + message: "Use 'is*' functions from lodash instead." +}]}]*/ + +import { isEmpty } from 'utils/collection-utils'; +``` + +::: + +::: incorrect { "sourceType": "module" } + +```js +/*eslint no-restricted-imports: ["error", { patterns: [{ + group: ["foo/*"], + importNamePattern: '^(is|has)', + message: "Use 'is*' and 'has*' functions from baz/bar instead" +}]}]*/ + +import { isSomething, hasSomething } from 'foo/bar'; +``` + +::: + +::: incorrect { "sourceType": "module" } + +```js +/*eslint no-restricted-imports: ["error", { patterns: [{ + group: ["foo/*"], + importNames: ["bar"], + importNamePattern: '^baz', +}]}]*/ + +import { bar, bazQux } from 'foo/quux'; +``` + +::: + +Examples of **correct** code for `importNamePattern` option: + ::: correct { "sourceType": "module" } ```js