eslint-plugin-restrict-replace-import 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +19 -0
- package/README.md +76 -0
- package/docs/rules/restrict-import.md +71 -0
- package/lib/index.js +22 -0
- package/lib/rules/restrict-import.js +133 -0
- package/package.json +47 -0
- package/tests/lib/rules/restrict-import.js +79 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
root: true,
|
|
5
|
+
extends: [
|
|
6
|
+
"eslint:recommended",
|
|
7
|
+
"plugin:eslint-plugin/recommended",
|
|
8
|
+
"plugin:node/recommended",
|
|
9
|
+
],
|
|
10
|
+
env: {
|
|
11
|
+
node: true,
|
|
12
|
+
},
|
|
13
|
+
overrides: [
|
|
14
|
+
{
|
|
15
|
+
files: ["tests/**/*.js"],
|
|
16
|
+
env: { mocha: true },
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
};
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# eslint-plugin-restrict-replace-import
|
|
2
|
+
|
|
3
|
+
ESLint Plugin for Restricting and Replacing Import.
|
|
4
|
+
|
|
5
|
+
Automatically fixable with replacement package!
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
You'll first need to install [ESLint](https://eslint.org/):
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm i eslint --save-dev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Next, install `eslint-plugin-restrict-replace-import`:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install eslint-plugin-restrict-replace-import --save-dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Add `restrict-import` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"plugins": ["restrict-import"]
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Then configure the rules you want to use under the rules section.
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"rules": {
|
|
36
|
+
"restrict-import/rule-name": [
|
|
37
|
+
"error",
|
|
38
|
+
["restricted-package1", "restricted-package2"]
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
You can also specify an alternative package to import instead:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"rules": {
|
|
49
|
+
"restrict-import/rule-name": [
|
|
50
|
+
"error",
|
|
51
|
+
[
|
|
52
|
+
{
|
|
53
|
+
"name": "restricted-package1",
|
|
54
|
+
"alternative": "replacement-package1"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "restricted-package2",
|
|
58
|
+
"alternative": "replacement-package2"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Rules
|
|
67
|
+
|
|
68
|
+
<!-- begin auto-generated rules list -->
|
|
69
|
+
|
|
70
|
+
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
|
|
71
|
+
|
|
72
|
+
| Name | Description | 🔧 |
|
|
73
|
+
| :----------------------------------------------- | :--------------------------------------- | :-- |
|
|
74
|
+
| [restrict-import](docs/rules/restrict-import.md) | Prevent the Import of a Specific Package | 🔧 |
|
|
75
|
+
|
|
76
|
+
<!-- end auto-generated rules list -->
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Prevent the Import of a Specific Package (`restrict-import/restrict-import`)
|
|
2
|
+
|
|
3
|
+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
|
|
4
|
+
|
|
5
|
+
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
7
|
+
This rule aims to prevent the import of a specific package.
|
|
8
|
+
|
|
9
|
+
With additional configuration, this rule can also suggest an alternative package to import instead.
|
|
10
|
+
|
|
11
|
+
If the alternative package is specified, auto-fixing will replace the import statement with the alternative package.
|
|
12
|
+
|
|
13
|
+
## Rule Details
|
|
14
|
+
|
|
15
|
+
Example configuration:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"rules": {
|
|
20
|
+
"restrict-import/restrict-import": [
|
|
21
|
+
"error",
|
|
22
|
+
[
|
|
23
|
+
{
|
|
24
|
+
"name": "test-package",
|
|
25
|
+
"alternative": "replacement-package"
|
|
26
|
+
},
|
|
27
|
+
"another-package"
|
|
28
|
+
]
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Examples of **incorrect** code for this rule:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import testPackage from "test-package";
|
|
38
|
+
|
|
39
|
+
import anotherPackage from "another-package";
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Examples of **correct** code for this rule:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import testPackage from "replacement-package";
|
|
46
|
+
|
|
47
|
+
import theOtherPackage from "the-other-package";
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Options
|
|
51
|
+
|
|
52
|
+
This rule takes a single argument, an array of strings or objects.
|
|
53
|
+
|
|
54
|
+
Each string or object represents a package that should be restricted.
|
|
55
|
+
|
|
56
|
+
If the array element is a string, it represents the name of the package that should be restricted.
|
|
57
|
+
|
|
58
|
+
If the array element is an object, it represents the name of the package that should be restricted and the alternative package that should be suggested instead.
|
|
59
|
+
|
|
60
|
+
The alternative package is optional.
|
|
61
|
+
|
|
62
|
+
Scheme:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
type Restriction =
|
|
66
|
+
| string
|
|
67
|
+
| {
|
|
68
|
+
target: string;
|
|
69
|
+
replacement?: string;
|
|
70
|
+
};
|
|
71
|
+
```
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview ESLint Plugin for Restricting Import
|
|
3
|
+
* @author shiwoo.park
|
|
4
|
+
*/
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
//------------------------------------------------------------------------------
|
|
8
|
+
// Requirements
|
|
9
|
+
//------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const requireIndex = require("requireindex");
|
|
12
|
+
|
|
13
|
+
//------------------------------------------------------------------------------
|
|
14
|
+
// Plugin Definition
|
|
15
|
+
//------------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
// import all rules in lib/rules
|
|
19
|
+
module.exports.rules = requireIndex(__dirname + "/rules");
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Prevent the Import of a Specific Package
|
|
3
|
+
* @author shiwoo.park
|
|
4
|
+
*/
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
/** @type {import('eslint').Rule.RuleModule} */
|
|
8
|
+
module.exports = {
|
|
9
|
+
meta: {
|
|
10
|
+
type: "problem",
|
|
11
|
+
docs: {
|
|
12
|
+
description:
|
|
13
|
+
"Prevent the Import of a Specific Package",
|
|
14
|
+
recommended: false,
|
|
15
|
+
url: "https://github.com/custardcream98/eslint-plugin-restrict-replace-import/blob/main/docs/rules/restrict-import.md",
|
|
16
|
+
},
|
|
17
|
+
fixable: "code",
|
|
18
|
+
|
|
19
|
+
messages: {
|
|
20
|
+
ImportRestriction:
|
|
21
|
+
"`{{ name }}` is restricted from being used.",
|
|
22
|
+
ImportRestrictionWithReplacement:
|
|
23
|
+
"`{{ name }}` is restricted from being used. Replace it with `{{ replacement }}`.",
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
schema: [
|
|
27
|
+
{
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
restrictedPackages: {
|
|
31
|
+
type: "array",
|
|
32
|
+
items: {
|
|
33
|
+
anyOf: [
|
|
34
|
+
{
|
|
35
|
+
type: "string",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "object",
|
|
39
|
+
properties: {
|
|
40
|
+
target: {
|
|
41
|
+
type: "string",
|
|
42
|
+
required: true,
|
|
43
|
+
},
|
|
44
|
+
replacement: {
|
|
45
|
+
type: "string",
|
|
46
|
+
required: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
create(context) {
|
|
59
|
+
const option = context.options[0];
|
|
60
|
+
|
|
61
|
+
const restrictedPackages = new Map();
|
|
62
|
+
|
|
63
|
+
option.restrictedPackages.forEach((packageName) => {
|
|
64
|
+
if (typeof packageName === "string") {
|
|
65
|
+
restrictedPackages.set(packageName, null);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
restrictedPackages.set(
|
|
70
|
+
packageName.target,
|
|
71
|
+
packageName.replacement
|
|
72
|
+
? packageName.replacement
|
|
73
|
+
: null
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const checkRestricted = (importSource) => {
|
|
78
|
+
const isRestricted =
|
|
79
|
+
restrictedPackages.has(importSource);
|
|
80
|
+
|
|
81
|
+
return isRestricted;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const getReplacement = (importSource) => {
|
|
85
|
+
const replacement =
|
|
86
|
+
restrictedPackages.get(importSource);
|
|
87
|
+
|
|
88
|
+
return replacement;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
ImportDeclaration(node) {
|
|
93
|
+
const importSource = node.source.value;
|
|
94
|
+
const importSourceType = node.source.type;
|
|
95
|
+
|
|
96
|
+
const isRestricted = checkRestricted(importSource);
|
|
97
|
+
|
|
98
|
+
if (
|
|
99
|
+
!isRestricted ||
|
|
100
|
+
importSourceType !== "Literal"
|
|
101
|
+
) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const replacement = getReplacement(importSource);
|
|
106
|
+
const quote = node.source.raw.includes("'")
|
|
107
|
+
? "'"
|
|
108
|
+
: '"';
|
|
109
|
+
|
|
110
|
+
context.report({
|
|
111
|
+
node,
|
|
112
|
+
messageId: replacement
|
|
113
|
+
? "ImportRestrictionWithReplacement"
|
|
114
|
+
: "ImportRestriction",
|
|
115
|
+
data: {
|
|
116
|
+
name: importSource,
|
|
117
|
+
replacement,
|
|
118
|
+
},
|
|
119
|
+
fix: (fixer) => {
|
|
120
|
+
if (!replacement) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return fixer.replaceText(
|
|
125
|
+
node.source,
|
|
126
|
+
`${quote}${replacement}${quote}`
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-restrict-replace-import",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "ESLint Plugin for Restricting and Replacing Import",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"eslint",
|
|
7
|
+
"eslintplugin",
|
|
8
|
+
"eslint-plugin",
|
|
9
|
+
"import",
|
|
10
|
+
"restrict"
|
|
11
|
+
],
|
|
12
|
+
"author": "shiwoo.park",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/custardcream98/eslint-plugin-restrict-replace-import/issues"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/custardcream98/eslint-plugin-restrict-replace-import.git"
|
|
19
|
+
},
|
|
20
|
+
"main": "./lib/index.js",
|
|
21
|
+
"exports": "./lib/index.js",
|
|
22
|
+
"scripts": {
|
|
23
|
+
"lint": "npm-run-all \"lint:*\"",
|
|
24
|
+
"lint:eslint-docs": "npm-run-all \"update:eslint-docs -- --check\"",
|
|
25
|
+
"lint:js": "eslint .",
|
|
26
|
+
"test": "mocha tests --recursive",
|
|
27
|
+
"update:eslint-docs": "eslint-doc-generator"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"requireindex": "^1.2.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"eslint": "^8.19.0",
|
|
34
|
+
"eslint-doc-generator": "^1.0.0",
|
|
35
|
+
"eslint-plugin-eslint-plugin": "^5.0.0",
|
|
36
|
+
"eslint-plugin-node": "^11.1.0",
|
|
37
|
+
"mocha": "^10.0.0",
|
|
38
|
+
"npm-run-all": "^4.1.5"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"eslint": ">=7"
|
|
45
|
+
},
|
|
46
|
+
"license": "ISC"
|
|
47
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Prevent the Import of a Specific Package
|
|
3
|
+
* @author shiwoo.park
|
|
4
|
+
*/
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
//------------------------------------------------------------------------------
|
|
8
|
+
// Requirements
|
|
9
|
+
//------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const rule = require("../../../lib/rules/restrict-import"),
|
|
12
|
+
RuleTester = require("eslint").RuleTester;
|
|
13
|
+
|
|
14
|
+
//------------------------------------------------------------------------------
|
|
15
|
+
// Tests
|
|
16
|
+
//------------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
const ruleTester = new RuleTester({
|
|
19
|
+
parserOptions: {
|
|
20
|
+
ecmaVersion: 2015,
|
|
21
|
+
sourceType: "module",
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const OPTIONS = [
|
|
26
|
+
{
|
|
27
|
+
restrictedPackages: [
|
|
28
|
+
"lodash",
|
|
29
|
+
{
|
|
30
|
+
target: "react",
|
|
31
|
+
replacement: "preact",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
ruleTester.run("restrict-import", rule, {
|
|
38
|
+
valid: [
|
|
39
|
+
{
|
|
40
|
+
code: "import _ from 'underscore'",
|
|
41
|
+
options: OPTIONS,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
code: "import _ from 'lodash-es'",
|
|
45
|
+
options: OPTIONS,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
code: "import { useState } from 'preact'",
|
|
49
|
+
options: OPTIONS,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
invalid: [
|
|
54
|
+
{
|
|
55
|
+
code: "import _ from 'lodash'",
|
|
56
|
+
errors: [
|
|
57
|
+
{
|
|
58
|
+
message:
|
|
59
|
+
"`lodash` is restricted from being used.",
|
|
60
|
+
type: "ImportDeclaration",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
options: OPTIONS,
|
|
64
|
+
output: null,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
code: "import { useState } from 'react'",
|
|
68
|
+
errors: [
|
|
69
|
+
{
|
|
70
|
+
message:
|
|
71
|
+
"`react` is restricted from being used. Replace it with `preact`.",
|
|
72
|
+
type: "ImportDeclaration",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
options: OPTIONS,
|
|
76
|
+
output: "import { useState } from 'preact'",
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
});
|