eslint-plugin-stratified-design 0.10.0 → 0.12.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/lib/rules/lower-level-imports.js +2 -0
- package/lib/rules/no-disallowed-imports.js +26 -14
- package/lib/rules/stratified-imports.js +2 -0
- package/package.json +2 -1
- package/tests/lib/rules/lower-level-imports.js +11 -2
- package/tests/lib/rules/no-disallowed-imports.js +50 -5
- package/tests/lib/rules/stratified-imports.js +10 -1
|
@@ -167,6 +167,8 @@ module.exports = {
|
|
|
167
167
|
const isFileIndex = isFileIndexOfModule(options, fileDir, filePath);
|
|
168
168
|
|
|
169
169
|
const report = (node) => {
|
|
170
|
+
if (node.importKind === "type") return;
|
|
171
|
+
|
|
170
172
|
if (isExcludedFile) return;
|
|
171
173
|
|
|
172
174
|
const { modulePath, isModuleExcluded } = createModulePath(
|
|
@@ -16,7 +16,7 @@ const { createAliases, fromCwd, match } = require("../helpers/common");
|
|
|
16
16
|
* @typedef {import('eslint').AST.Token} Token
|
|
17
17
|
* @typedef {import('eslint').SourceCode} SourceCode
|
|
18
18
|
* @typedef {{
|
|
19
|
-
* import: { member: string[], from: string },
|
|
19
|
+
* import: { member: '*' | string[], from: string },
|
|
20
20
|
* allow: string[],
|
|
21
21
|
* disallow: string[],
|
|
22
22
|
* }} ImportPath
|
|
@@ -30,6 +30,8 @@ const DEFAULT = "default";
|
|
|
30
30
|
|
|
31
31
|
const NAMESPACE = "*";
|
|
32
32
|
|
|
33
|
+
const ANY_MEMBER = "*";
|
|
34
|
+
|
|
33
35
|
const importSchema = {
|
|
34
36
|
type: "object",
|
|
35
37
|
properties: {
|
|
@@ -37,8 +39,16 @@ const importSchema = {
|
|
|
37
39
|
type: "object",
|
|
38
40
|
properties: {
|
|
39
41
|
member: {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
oneOf: [
|
|
43
|
+
{
|
|
44
|
+
type: "array",
|
|
45
|
+
items: [{ type: "string" }], // 'default' means default specifier
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "string",
|
|
49
|
+
pattern: `^[${ANY_MEMBER}]$`
|
|
50
|
+
}
|
|
51
|
+
]
|
|
42
52
|
},
|
|
43
53
|
from: { type: "string" },
|
|
44
54
|
},
|
|
@@ -93,7 +103,7 @@ module.exports = {
|
|
|
93
103
|
additionalItems: false,
|
|
94
104
|
},
|
|
95
105
|
messages: {
|
|
96
|
-
"no-disallowed-imports": "
|
|
106
|
+
"no-disallowed-imports": "{{member}} should NOT be imported from '{{from}}'",
|
|
97
107
|
},
|
|
98
108
|
},
|
|
99
109
|
create(context) {
|
|
@@ -126,6 +136,10 @@ module.exports = {
|
|
|
126
136
|
return [theMember, theImportSpec];
|
|
127
137
|
}
|
|
128
138
|
|
|
139
|
+
if (importSpec.import.member === ANY_MEMBER) {
|
|
140
|
+
return ['Any member', importSpec]
|
|
141
|
+
}
|
|
142
|
+
|
|
129
143
|
const importedSpecifiers = node.specifiers.map((specifier) => {
|
|
130
144
|
if (specifier.type === "ImportSpecifier")
|
|
131
145
|
return specifier.imported.name;
|
|
@@ -143,16 +157,14 @@ module.exports = {
|
|
|
143
157
|
match(fromCwd(context.cwd, modulePath))(importSpec.import.from)
|
|
144
158
|
) {
|
|
145
159
|
if (member === DEFAULT || member === NAMESPACE) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
importSpec,
|
|
153
|
-
];
|
|
160
|
+
const theMember = node.specifiers.find(
|
|
161
|
+
({ type }) =>
|
|
162
|
+
type === "ImportDefaultSpecifier" ||
|
|
163
|
+
type === "ImportNamespaceSpecifier"
|
|
164
|
+
).local.name
|
|
165
|
+
return [`'${theMember}'`, importSpec];
|
|
154
166
|
}
|
|
155
|
-
return [member
|
|
167
|
+
return [`'${member}'`, importSpec];
|
|
156
168
|
}
|
|
157
169
|
|
|
158
170
|
return [undefined, undefined];
|
|
@@ -174,7 +186,7 @@ module.exports = {
|
|
|
174
186
|
context.report({
|
|
175
187
|
node,
|
|
176
188
|
messageId: "no-disallowed-imports",
|
|
177
|
-
data: { member: theMember },
|
|
189
|
+
data: { member: theMember, from: theImportSpec.import.from },
|
|
178
190
|
});
|
|
179
191
|
},
|
|
180
192
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-stratified-design",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "ESlint rules for stratified design",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"requireindex": "^1.2.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
+
"@typescript-eslint/parser": "^7.1.0",
|
|
30
31
|
"eslint": "^8.19.0",
|
|
31
32
|
"eslint-plugin-eslint-plugin": "^5.0.0",
|
|
32
33
|
"eslint-plugin-node": "^11.1.0",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
//------------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
const rule = require("../../../lib/rules/lower-level-imports"),
|
|
12
|
-
RuleTester = require("eslint").RuleTester
|
|
12
|
+
RuleTester = require("eslint").RuleTester,
|
|
13
|
+
path = require("path");
|
|
13
14
|
|
|
14
15
|
//------------------------------------------------------------------------------
|
|
15
16
|
// Tests
|
|
@@ -28,7 +29,10 @@ const structure = [
|
|
|
28
29
|
];
|
|
29
30
|
|
|
30
31
|
const ruleTester = new RuleTester({
|
|
31
|
-
|
|
32
|
+
parser: path.resolve(
|
|
33
|
+
"./node_modules/@typescript-eslint/parser/dist/parser.js"
|
|
34
|
+
),
|
|
35
|
+
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
|
|
32
36
|
});
|
|
33
37
|
|
|
34
38
|
ruleTester.run("lower-level-imports", rule, {
|
|
@@ -232,6 +236,11 @@ ruleTester.run("lower-level-imports", rule, {
|
|
|
232
236
|
filename: "./src/layer1/subLayer2.js",
|
|
233
237
|
options: [{ structure, root: "./src", aliases: { "@/": "./src/" } }],
|
|
234
238
|
},
|
|
239
|
+
{
|
|
240
|
+
code: "import type { SomeType } from '@/layer2/subLayer2'",
|
|
241
|
+
filename: "./src/layer1/subLayer2.js",
|
|
242
|
+
options: [{ structure, root: "./src", aliases: { "@/": "./src/" } }],
|
|
243
|
+
},
|
|
235
244
|
],
|
|
236
245
|
invalid: [
|
|
237
246
|
{
|
|
@@ -131,6 +131,34 @@ ruleTester.run("no-disallowed-imports", rule, {
|
|
|
131
131
|
},
|
|
132
132
|
],
|
|
133
133
|
},
|
|
134
|
+
{
|
|
135
|
+
code: "import { anyMember } from './fileA'",
|
|
136
|
+
filename: "./src/fileB.js",
|
|
137
|
+
options: [
|
|
138
|
+
{
|
|
139
|
+
imports: [
|
|
140
|
+
{
|
|
141
|
+
import: { member: "*", from: "src/fileA" },
|
|
142
|
+
allow: ["src/**/*.js"],
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
code: "import * as namespace from './fileA'",
|
|
150
|
+
filename: "./src/fileB.js",
|
|
151
|
+
options: [
|
|
152
|
+
{
|
|
153
|
+
imports: [
|
|
154
|
+
{
|
|
155
|
+
import: { member: "*", from: "src/fileA" },
|
|
156
|
+
allow: ["src/**/*.js"],
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
134
162
|
],
|
|
135
163
|
invalid: [
|
|
136
164
|
{
|
|
@@ -146,7 +174,7 @@ ruleTester.run("no-disallowed-imports", rule, {
|
|
|
146
174
|
],
|
|
147
175
|
},
|
|
148
176
|
],
|
|
149
|
-
errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
|
|
177
|
+
errors: [{ messageId: "no-disallowed-imports", data: { member: "'foo'", from: "src/fileA" } }],
|
|
150
178
|
},
|
|
151
179
|
{
|
|
152
180
|
code: "import { foo } from './fileA'",
|
|
@@ -161,7 +189,7 @@ ruleTester.run("no-disallowed-imports", rule, {
|
|
|
161
189
|
],
|
|
162
190
|
},
|
|
163
191
|
],
|
|
164
|
-
errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
|
|
192
|
+
errors: [{ messageId: "no-disallowed-imports", data: { member: "'foo'", from: "src/fileA" } }],
|
|
165
193
|
},
|
|
166
194
|
{
|
|
167
195
|
code: "import { foo } from './fileA'",
|
|
@@ -177,7 +205,7 @@ ruleTester.run("no-disallowed-imports", rule, {
|
|
|
177
205
|
],
|
|
178
206
|
},
|
|
179
207
|
],
|
|
180
|
-
errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
|
|
208
|
+
errors: [{ messageId: "no-disallowed-imports", data: { member: "'foo'", from: "src/fileA" } }],
|
|
181
209
|
},
|
|
182
210
|
{
|
|
183
211
|
code: "import foo from './fileA'",
|
|
@@ -192,7 +220,7 @@ ruleTester.run("no-disallowed-imports", rule, {
|
|
|
192
220
|
],
|
|
193
221
|
},
|
|
194
222
|
],
|
|
195
|
-
errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
|
|
223
|
+
errors: [{ messageId: "no-disallowed-imports", data: { member: "'foo'", from: "src/fileA" } }],
|
|
196
224
|
},
|
|
197
225
|
{
|
|
198
226
|
code: "import * as name from './fileA'",
|
|
@@ -208,7 +236,24 @@ ruleTester.run("no-disallowed-imports", rule, {
|
|
|
208
236
|
},
|
|
209
237
|
],
|
|
210
238
|
errors: [
|
|
211
|
-
{ messageId: "no-disallowed-imports", data: { member: "name" } },
|
|
239
|
+
{ messageId: "no-disallowed-imports", data: { member: "'name'", from: "src/fileA" } },
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
code: "import { anyMember } from './fileA'",
|
|
244
|
+
filename: "./src/fileB.js",
|
|
245
|
+
options: [
|
|
246
|
+
{
|
|
247
|
+
imports: [
|
|
248
|
+
{
|
|
249
|
+
import: { member: "*", from: "src/fileA" },
|
|
250
|
+
disallow: ["src/**/*.js"],
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
errors: [
|
|
256
|
+
{ messageId: "no-disallowed-imports", data: { member: "Any member", from: "src/fileA" } },
|
|
212
257
|
],
|
|
213
258
|
},
|
|
214
259
|
],
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
const rule = require("../../../lib/rules/stratified-imports");
|
|
12
12
|
const RuleTester = require("eslint").RuleTester;
|
|
13
|
+
const path = require("path");
|
|
13
14
|
|
|
14
15
|
//------------------------------------------------------------------------------
|
|
15
16
|
// Tests
|
|
@@ -57,7 +58,10 @@ const RuleTester = require("eslint").RuleTester;
|
|
|
57
58
|
*/
|
|
58
59
|
|
|
59
60
|
const ruleTester = new RuleTester({
|
|
60
|
-
|
|
61
|
+
parser: path.resolve(
|
|
62
|
+
"./node_modules/@typescript-eslint/parser/dist/parser.js"
|
|
63
|
+
),
|
|
64
|
+
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
|
|
61
65
|
});
|
|
62
66
|
|
|
63
67
|
ruleTester.run("stratified-imports", rule, {
|
|
@@ -162,6 +166,11 @@ ruleTester.run("stratified-imports", rule, {
|
|
|
162
166
|
filename: "./mocked/stratified-imports/layerA.js",
|
|
163
167
|
options: [{ aliases: { "@/": "./mocked/stratified-imports/" } }],
|
|
164
168
|
},
|
|
169
|
+
{
|
|
170
|
+
code: "import type { SomeType } from './layerA'",
|
|
171
|
+
filename: "./mocked/stratified-imports/layerB.js",
|
|
172
|
+
options: [],
|
|
173
|
+
},
|
|
165
174
|
],
|
|
166
175
|
invalid: [
|
|
167
176
|
{
|