eslint-plugin-stratified-design 0.8.0-beta.3 → 0.9.0-beta

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.
@@ -125,6 +125,17 @@ The default is as follows:
125
125
  }
126
126
  ```
127
127
 
128
+ Imported modules can be excluded from the rule (`lower-level-imports`) using the `excludeImports` option:
129
+
130
+ ```json
131
+ {
132
+ "stratified-design/lower-level-imports": [
133
+ "error",
134
+ { "excludeImports": ["**/*.css"] }
135
+ ]
136
+ }
137
+ ```
138
+
128
139
  ## Rule Details
129
140
 
130
141
  If a file structure is as follows:
@@ -0,0 +1,90 @@
1
+ # Allow or disallow importing specified modules (no-disallowed-imports)
2
+
3
+ In certain cases, it is necessary to restrict the importation of specific modules. For instance:
4
+
5
+ - In a stratified design approach, higher-level modules should not be imported into lower-level modules.
6
+ - There may be situations where global variables should only be writable within a specific context.
7
+
8
+ ## Options
9
+
10
+ To control module imports, use the `imports` option:
11
+
12
+ ```json
13
+ {
14
+ "stratified-design/no-disallowed-imports": [
15
+ "error",
16
+ {
17
+ "imports": [
18
+ {
19
+ "import": { "member": ["foo"], "from": "**/src/fileA" },
20
+ "allow": ["**/src/some-dir/*.js"]
21
+ },
22
+ {
23
+ "import": { "member": ["foo", "bar"], "from": "**/src/fileB" },
24
+ "disallow": ["**/src/not-allowed-file.js"]
25
+ },
26
+ {
27
+ "import": { "member": ["baz"], "from": "**/src/fileC" },
28
+ "allow": ["**/src/some-dir/*.js"],
29
+ "disallow": ["**/src/not-allowed-file.js"]
30
+ }
31
+ ]
32
+ }
33
+ ]
34
+ }
35
+ ```
36
+
37
+ If an imported module uses an alias, you can register the alias with the `aliases` option:
38
+
39
+ ```json
40
+ {
41
+ "stratified-design/no-disallowed-imports": [
42
+ "error",
43
+ {
44
+ "aliases": { "@/": "./src/" }
45
+ }
46
+ ]
47
+ }
48
+ ```
49
+
50
+ ## Rule Details
51
+
52
+ Examples of **incorrect** code for this rule:
53
+
54
+ ```js
55
+ // "stratified-design/no-disallowed-imports": [
56
+ // "error",
57
+ // {
58
+ // "imports": [
59
+ // {
60
+ // "import": { "member": ["foo"], "from": "**/src/fileA" },
61
+ // "allow": ["**/src/**/fileB.js"],
62
+ // "disallow": ["**/src/**/fileC.*"]
63
+ // }
64
+ // ]
65
+ // }
66
+ // ]
67
+
68
+ // ./src/fileC.js
69
+ import { foo } from "./fileA";
70
+ ```
71
+
72
+ Examples of **correct** code for this rule:
73
+
74
+ ```js
75
+ // "stratified-design/no-disallowed-imports": [
76
+ // "error",
77
+ // {
78
+ // "imports": [
79
+ // {
80
+ // "import": { "member": ["foo"], "from": "**/src/fileA" },
81
+ // "allow": ["**/src/**/fileB.js"],
82
+ // "disallow": ["**/src/**/fileC.*"]
83
+ // }
84
+ // ]
85
+ // }
86
+ // ]
87
+
88
+ // ./src/fileB.js
89
+ import { foo } from "./fileA";
90
+ ```
@@ -68,7 +68,7 @@ You can register the files to which the rule (`stratified-imports`) should apply
68
68
 
69
69
  ```json
70
70
  {
71
- "stratified-design/lower-level-imports": [
71
+ "stratified-design/stratified-imports": [
72
72
  "error",
73
73
  { "include": ["**/*.js"], "exclude": ["**/*.test.js"] }
74
74
  ]
@@ -84,6 +84,17 @@ The default configuration is as follows:
84
84
  }
85
85
  ```
86
86
 
87
+ Imported modules can be excluded from the rule (`stratified-imports`) using the `excludeImports` option:
88
+
89
+ ```json
90
+ {
91
+ "stratified-design/stratified-imports": [
92
+ "error",
93
+ { "excludeImports": ["**/*.css"] }
94
+ ]
95
+ }
96
+ ```
97
+
87
98
  ## Rule Details
88
99
 
89
100
  Consider the following folder structure:
@@ -1,5 +1,9 @@
1
1
  const p = require("path");
2
2
 
3
+ /**
4
+ * @typedef {{alias: string, path: string}[]} Aliases
5
+ */
6
+
3
7
  // @level 2
4
8
  /**
5
9
  * @param {string} from
@@ -81,6 +85,37 @@ const reducedPaths = (path) => {
81
85
  }, []);
82
86
  };
83
87
 
88
+ // @level 1
89
+ /**
90
+ * @param {Record<string, string>} rawAliases
91
+ * @returns {Aliases}
92
+ */
93
+ const createAliases = (rawAliases) => {
94
+ return Object.keys(rawAliases)
95
+ .sort((a, b) => b.length - a.length)
96
+ .map((alias) => ({ alias, path: rawAliases[alias] }));
97
+ };
98
+
99
+ // @level 1
100
+ /**
101
+ * Replace an alias into the corresponding path
102
+ * @param {string} cwd
103
+ * @param {string} fileDir
104
+ * @param {Aliases} aliases
105
+ */
106
+ const replaceAlias = (cwd, fileDir, aliases) => {
107
+ /**
108
+ * @param {string} moduleSource
109
+ */
110
+ return (moduleSource) => {
111
+ const { alias, path } =
112
+ aliases.find(({ alias }) => moduleSource.startsWith(alias)) || {};
113
+ if (!alias) return moduleSource;
114
+ const modulePath = resolvePath(cwd, moduleSource.replace(alias, path));
115
+ return toRelative(fileDir, modulePath);
116
+ };
117
+ };
118
+
84
119
  module.exports = {
85
120
  toRelative,
86
121
  toSegments,
@@ -92,4 +127,6 @@ module.exports = {
92
127
  equal,
93
128
  readArray,
94
129
  reducedPaths,
130
+ createAliases,
131
+ replaceAlias,
95
132
  };
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ const { replaceAlias, resolvePath, parsePath } = require("./common");
4
+
5
+ /**
6
+ * @param {string} contextFileSource
7
+ */
8
+ const parseFileSource = (contextFileSource) => {
9
+ const fileSource = resolvePath(contextFileSource);
10
+ const parsedFileSource = parsePath(fileSource);
11
+ const fileDir = resolvePath(parsedFileSource.dir);
12
+ return { fileDir, fileSource };
13
+ };
14
+
15
+ /**
16
+ * @param {string} cwd
17
+ * @param {string} fileDir
18
+ * @param {import("./common").Aliases} aliases
19
+ */
20
+ const createModulePath = (cwd, fileDir, aliases) => {
21
+ /**
22
+ * @param {string} moduleSourceWithAlias
23
+ */
24
+ return (moduleSourceWithAlias) => {
25
+ const moduleSource = replaceAlias(
26
+ cwd,
27
+ fileDir,
28
+ aliases
29
+ )(moduleSourceWithAlias);
30
+ const isNodeModule = moduleSource.startsWith(".") === false;
31
+ const modulePath = isNodeModule
32
+ ? moduleSource
33
+ : resolvePath(fileDir, moduleSource);
34
+ return modulePath;
35
+ };
36
+ };
37
+
38
+ module.exports = { parseFileSource, createModulePath };
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  const { minimatch } = require("minimatch");
4
- const { resolvePath, reducedPaths, parsePath } = require("../common");
5
4
  const {
5
+ resolvePath,
6
+ reducedPaths,
7
+ parsePath,
6
8
  replaceAlias,
9
+ } = require("../common");
10
+ const {
7
11
  findLevel,
8
12
  findLayerWithReducedPath,
9
13
  readStructure,
@@ -56,7 +60,7 @@ const parseFileSource = (options, contextFileSource) => {
56
60
  * @param {string} cwd
57
61
  * @param {string[]} excludeImports
58
62
  * @param {string} fileDir
59
- * @param {import('./2 layer').Aliases} aliases
63
+ * @param {import("../common").Aliases} aliases
60
64
  */
61
65
  const createModulePath = (cwd, excludeImports, fileDir, aliases) => {
62
66
  /**
@@ -29,10 +29,6 @@ const {
29
29
  * @typedef {RawLayer[][]} RawStructure
30
30
  */
31
31
 
32
- /**
33
- * @typedef {{alias: string, path: string}[]} Aliases
34
- */
35
-
36
32
  // @level 2
37
33
  /**
38
34
  * @param {string} fileDir
@@ -105,37 +101,6 @@ const toStructure = (rawStructure, fileDir) => {
105
101
  });
106
102
  };
107
103
 
108
- // @level 2
109
- /**
110
- * @param {Record<string, string>} rawAliases
111
- * @returns {Aliases}
112
- */
113
- const createAliases = (rawAliases) => {
114
- return Object.keys(rawAliases)
115
- .sort((a, b) => b.length - a.length)
116
- .map((alias) => ({ alias, path: rawAliases[alias] }));
117
- };
118
-
119
- // @level 2
120
- /**
121
- * Replace an alias into the corresponding path
122
- * @param {string} cwd
123
- * @param {string} fileDir
124
- * @param {Aliases} aliases
125
- */
126
- const replaceAlias = (cwd, fileDir, aliases) => {
127
- /**
128
- * @param {string} moduleSource
129
- */
130
- return (moduleSource) => {
131
- const { alias, path } =
132
- aliases.find(({ alias }) => moduleSource.startsWith(alias)) || {};
133
- if (!alias) return moduleSource;
134
- const modulePath = resolvePath(cwd, moduleSource.replace(alias, path));
135
- return toRelative(fileDir, modulePath);
136
- };
137
- };
138
-
139
104
  // @level 2
140
105
  /**
141
106
  * Find the layer level for a module
@@ -238,8 +203,6 @@ const readStructure = (dir) => {
238
203
  module.exports = {
239
204
  readRawStructure,
240
205
  toStructure,
241
- createAliases,
242
- replaceAlias,
243
206
  findLevel,
244
207
  findLayerWithReducedPath,
245
208
  isNotRegisteredNodeModule,
@@ -0,0 +1,180 @@
1
+ /**
2
+ * @fileoverview ...
3
+ * @author Hodoug Joung
4
+ */
5
+ "use strict";
6
+
7
+ const { minimatch } = require("minimatch");
8
+ const helpers = require("../helpers/noDisallowedImports");
9
+ const { createAliases } = require("../helpers/common");
10
+
11
+ //------------------------------------------------------------------------------
12
+ // Rule Definition
13
+ //------------------------------------------------------------------------------
14
+
15
+ /**
16
+ * @typedef {import('eslint').Rule.Node} Node
17
+ * @typedef {import('eslint').AST.Token} Token
18
+ * @typedef {import('eslint').SourceCode} SourceCode
19
+ * @typedef {{
20
+ * import: { member: string[], from: string },
21
+ * allow: string[],
22
+ * disallow: string[],
23
+ * }} ImportPath
24
+ * @typedef {{
25
+ * imports: ImportPath[],
26
+ * aliases: Record<string, string>
27
+ * }} Options
28
+ */
29
+
30
+ const DEFAULT = "default";
31
+
32
+ const importSchema = {
33
+ type: "object",
34
+ properties: {
35
+ import: {
36
+ type: "object",
37
+ properties: {
38
+ member: {
39
+ type: "array",
40
+ items: [{ type: "string" }], // 'default' means default specifier
41
+ },
42
+ from: { type: "string" },
43
+ },
44
+ required: ["member", "from"],
45
+ additionalProperties: false,
46
+ },
47
+ allow: {
48
+ type: "array",
49
+ items: [{ type: "string" }],
50
+ },
51
+ disallow: {
52
+ type: "array",
53
+ items: [{ type: "string" }],
54
+ },
55
+ },
56
+ required: ["import"],
57
+ additionalProperties: false,
58
+ };
59
+
60
+ const aliasesSchema = {
61
+ type: "object",
62
+ patternProperties: {
63
+ ["^.+$"]: {
64
+ type: "string",
65
+ pattern: "^\\.{1,2}(/[^/]+)*/?$",
66
+ },
67
+ },
68
+ additionalProperties: false,
69
+ };
70
+
71
+ /** @type {import('eslint').Rule.RuleModule} */
72
+ module.exports = {
73
+ meta: {
74
+ type: "problem",
75
+ fixable: "code",
76
+ schema: {
77
+ type: "array",
78
+ items: [
79
+ {
80
+ type: "object",
81
+ properties: {
82
+ imports: {
83
+ type: "array",
84
+ items: [importSchema],
85
+ },
86
+ aliases: aliasesSchema,
87
+ },
88
+ required: ["imports"],
89
+ additionalProperties: false,
90
+ },
91
+ ],
92
+ additionalItems: false,
93
+ },
94
+ messages: {
95
+ "no-disallowed-imports": "'{{member}}' should NOT be imported",
96
+ },
97
+ },
98
+ create(context) {
99
+ /**
100
+ * @type {Options}
101
+ */
102
+ const options = {
103
+ imports: [],
104
+ aliases: {},
105
+ ...(context.options[0] || {}),
106
+ };
107
+ const { fileDir, fileSource } = helpers.parseFileSource(context.filename);
108
+ const createModulePath = helpers.createModulePath(
109
+ context.cwd,
110
+ fileDir,
111
+ createAliases(options.aliases)
112
+ );
113
+ return {
114
+ ImportDeclaration(node) {
115
+ const modulePath = createModulePath(node.source.value);
116
+ /**
117
+ * @param {[string | undefined, ImportPath | undefined]} param0
118
+ * @param {ImportPath} importSpec
119
+ */
120
+ const searchTheImportPath = (
121
+ [theMember, theImportSpec],
122
+ importSpec
123
+ ) => {
124
+ if (theMember && theImportSpec) {
125
+ return [theMember, theImportSpec];
126
+ }
127
+
128
+ // const { member, from } = importSpec.import;
129
+
130
+ const importedSpecifiers = node.specifiers.map((specifier) => {
131
+ if (specifier.type === "ImportSpecifier")
132
+ return specifier.imported.name;
133
+ if (specifier.type === "ImportDefaultSpecifier") return DEFAULT;
134
+ return "";
135
+ });
136
+
137
+ const member = importSpec.import.member.find((specifier) =>
138
+ importedSpecifiers.some((sp) => sp === specifier)
139
+ );
140
+
141
+ if (member && minimatch(modulePath, importSpec.import.from)) {
142
+ if (member === DEFAULT) {
143
+ return [
144
+ node.specifiers.find(
145
+ ({ type }) => type === "ImportDefaultSpecifier"
146
+ ).local.name,
147
+ importSpec,
148
+ ];
149
+ }
150
+ return [member, importSpec];
151
+ }
152
+
153
+ return [undefined, undefined];
154
+ };
155
+
156
+ const [theMember, theImportSpec] = options.imports.reduce(
157
+ searchTheImportPath,
158
+ [undefined, undefined]
159
+ );
160
+ if (!theMember || !theImportSpec) return;
161
+
162
+ const { allow, disallow } = theImportSpec;
163
+ const isAllowed =
164
+ (allow
165
+ ? Boolean(allow.find((pattern) => minimatch(fileSource, pattern)))
166
+ : true) &&
167
+ (disallow
168
+ ? !disallow.find((pattern) => minimatch(fileSource, pattern))
169
+ : true);
170
+ if (isAllowed) return;
171
+
172
+ context.report({
173
+ node,
174
+ messageId: "no-disallowed-imports",
175
+ data: { member: theMember },
176
+ });
177
+ },
178
+ };
179
+ },
180
+ };
@@ -11,6 +11,8 @@ const path = require("path");
11
11
  // Rule Definition
12
12
  //------------------------------------------------------------------------------
13
13
 
14
+ // FIXME: const Body = styled.div``; const Body2 = styled(Body)`` (TaggedTemplateExpression)
15
+
14
16
  /**
15
17
  * @typedef {import('eslint').Rule.Node} Node
16
18
  * @typedef {import('eslint').AST.Token} Token
@@ -5,11 +5,11 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const { parsePath } = require("../helpers/common");
9
8
  //------------------------------------------------------------------------------
10
9
  // Requirements
11
10
  //------------------------------------------------------------------------------
12
11
 
12
+ const { parsePath, createAliases } = require("../helpers/common");
13
13
  const helper = require("../helpers/stratifiedImports");
14
14
 
15
15
  //------------------------------------------------------------------------------
@@ -87,7 +87,7 @@ module.exports = {
87
87
  context.cwd,
88
88
  options.excludeImports,
89
89
  fileDir,
90
- helper.createAliases(options.aliases)
90
+ createAliases(options.aliases)
91
91
  );
92
92
 
93
93
  const isInChildren = helper.isInChildren(fileDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-stratified-design",
3
- "version": "0.8.0-beta.3",
3
+ "version": "0.9.0-beta",
4
4
  "description": "ESlint rules for stratified design",
5
5
  "keywords": [
6
6
  "eslint",
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @fileoverview test for helpers/common.js
3
+ * @author Hodoug Joung
4
+ */
5
+ "use strict";
6
+
7
+ //------------------------------------------------------------------------------
8
+ // Requirements
9
+ //------------------------------------------------------------------------------
10
+
11
+ const assert = require("assert");
12
+ const { createAliases, replaceAlias } = require("../../../lib/helpers/common");
13
+
14
+ //------------------------------------------------------------------------------
15
+ // Tests
16
+ //------------------------------------------------------------------------------
17
+
18
+ describe("helpers/common", () => {
19
+ describe("createAliases()", () => {
20
+ const testCases = [
21
+ {
22
+ rawAliases: { "@/": "./src/" },
23
+ aliases: [{ alias: "@/", path: "./src/" }],
24
+ },
25
+ {
26
+ rawAliases: { "@/": "./src/", "@layer/": "./src/layer/" },
27
+ aliases: [
28
+ { alias: "@layer/", path: "./src/layer/" },
29
+ { alias: "@/", path: "./src/" },
30
+ ],
31
+ },
32
+ ];
33
+ testCases.forEach(({ rawAliases, aliases }) => {
34
+ it(`${JSON.stringify(rawAliases)} -> ${JSON.stringify(aliases)}`, () => {
35
+ assert.deepEqual(createAliases(rawAliases), aliases);
36
+ });
37
+ });
38
+ });
39
+
40
+ describe("replaceAlias()", () => {
41
+ const cwd = "/proj";
42
+ const fileDir = "/proj/src/layerA";
43
+ const aliases = [{ alias: "@/", path: "./src/" }];
44
+ const testCases = [
45
+ { moduleSource: "@/layerA/layerAA", relPath: "./layerAA" },
46
+ { moduleSource: "nodeModule", relPath: "nodeModule" },
47
+ ];
48
+ testCases.forEach(({ moduleSource, relPath }) => {
49
+ it(`${moduleSource} -> ${relPath}`, () => {
50
+ assert.equal(
51
+ replaceAlias(cwd, fileDir, aliases)(moduleSource),
52
+ relPath
53
+ );
54
+ });
55
+ });
56
+ });
57
+ });
@@ -13,8 +13,6 @@ const {
13
13
  findLevel,
14
14
  findLayerWithReducedPath,
15
15
  toStructure,
16
- createAliases,
17
- replaceAlias,
18
16
  validateRawStructure,
19
17
  isInParent,
20
18
  isInChildren,
@@ -52,45 +50,6 @@ describe("helpers/stratified-imports", () => {
52
50
  });
53
51
  });
54
52
 
55
- describe("createAliases()", () => {
56
- const testCases = [
57
- {
58
- rawAliases: { "@/": "./src/" },
59
- aliases: [{ alias: "@/", path: "./src/" }],
60
- },
61
- {
62
- rawAliases: { "@/": "./src/", "@layer/": "./src/layer/" },
63
- aliases: [
64
- { alias: "@layer/", path: "./src/layer/" },
65
- { alias: "@/", path: "./src/" },
66
- ],
67
- },
68
- ];
69
- testCases.forEach(({ rawAliases, aliases }) => {
70
- it(`${JSON.stringify(rawAliases)} -> ${JSON.stringify(aliases)}`, () => {
71
- assert.deepEqual(createAliases(rawAliases), aliases);
72
- });
73
- });
74
- });
75
-
76
- describe("replaceAlias()", () => {
77
- const cwd = "/proj";
78
- const fileDir = "/proj/src/layerA";
79
- const aliases = [{ alias: "@/", path: "./src/" }];
80
- const testCases = [
81
- { moduleSource: "@/layerA/layerAA", relPath: "./layerAA" },
82
- { moduleSource: "nodeModule", relPath: "nodeModule" },
83
- ];
84
- testCases.forEach(({ moduleSource, relPath }) => {
85
- it(`${moduleSource} -> ${relPath}`, () => {
86
- assert.equal(
87
- replaceAlias(cwd, fileDir, aliases)(moduleSource),
88
- relPath
89
- );
90
- });
91
- });
92
- });
93
-
94
53
  describe("findLevel()", () => {
95
54
  const structure = [[{ name: "/src/layerA" }], [{ name: "/src/layerB" }]];
96
55
  const testCases = [
@@ -0,0 +1,184 @@
1
+ /**
2
+ * @fileoverview Allow or disallow importing specified modules
3
+ * @author Hodoug Joung
4
+ */
5
+ "use strict";
6
+
7
+ //------------------------------------------------------------------------------
8
+ // Requirements
9
+ //------------------------------------------------------------------------------
10
+
11
+ const rule = require("../../../lib/rules/no-disallowed-imports");
12
+ const RuleTester = require("eslint").RuleTester;
13
+
14
+ //------------------------------------------------------------------------------
15
+ // Tests
16
+ //------------------------------------------------------------------------------
17
+
18
+ const ruleTester = new RuleTester({
19
+ parserOptions: {
20
+ ecmaVersion: 2022,
21
+ sourceType: "module",
22
+ ecmaFeatures: {
23
+ jsx: true,
24
+ },
25
+ },
26
+ });
27
+
28
+ ruleTester.run("no-disallowed-imports", rule, {
29
+ valid: [
30
+ {
31
+ code: "import { foo } from './fileA'",
32
+ filename: "./src/fileB.js",
33
+ options: [],
34
+ },
35
+ {
36
+ code: "import { foo } from './fileA'",
37
+ filename: "./src/fileB.js",
38
+ options: [
39
+ {
40
+ imports: [{ import: { member: ["foo"], from: "**/src/fileA" } }],
41
+ },
42
+ ],
43
+ },
44
+ {
45
+ code: "import { foo } from './fileA'",
46
+ filename: "./src/fileB.js",
47
+ options: [
48
+ {
49
+ imports: [
50
+ {
51
+ import: { member: ["baz"], from: "**/src/fileC" },
52
+ allow: ["**/src/**/*.js"],
53
+ },
54
+ {
55
+ import: { member: ["foo", "bar"], from: "**/src/fileA" },
56
+ allow: ["**/src/**/*.js"],
57
+ },
58
+ ],
59
+ },
60
+ ],
61
+ },
62
+ {
63
+ code: "import { foo } from './fileA'",
64
+ filename: "./src/fileB.js",
65
+ options: [
66
+ {
67
+ imports: [
68
+ {
69
+ import: { member: ["foo", "bar"], from: "**/src/fileA" },
70
+ disallow: ["**/src/**/*.test.js"],
71
+ },
72
+ ],
73
+ },
74
+ ],
75
+ },
76
+ {
77
+ code: "import { foo } from './fileA'",
78
+ filename: "./src/fileB.js",
79
+ options: [
80
+ {
81
+ imports: [
82
+ {
83
+ import: { member: ["foo", "bar"], from: "**/src/fileA" },
84
+ allow: ["**/src/**/*.js"],
85
+ disallow: ["**/src/**/*.test.js"],
86
+ },
87
+ ],
88
+ },
89
+ ],
90
+ },
91
+ {
92
+ code: "import { foo } from '@/fileA'",
93
+ filename: "./src/fileB.js",
94
+ options: [
95
+ {
96
+ imports: [
97
+ {
98
+ import: { member: ["foo"], from: "**/src/fileA" },
99
+ allow: ["**/src/**/*.js"],
100
+ },
101
+ ],
102
+ aliases: { "@/": "./src/" },
103
+ },
104
+ ],
105
+ },
106
+ {
107
+ code: "import foo from './fileA'",
108
+ filename: "./src/fileB.js",
109
+ options: [
110
+ {
111
+ imports: [
112
+ {
113
+ import: { member: ["default"], from: "**/src/fileA" },
114
+ allow: ["**/src/**/*.js"],
115
+ },
116
+ ],
117
+ },
118
+ ],
119
+ },
120
+ ],
121
+ invalid: [
122
+ {
123
+ code: "import { foo } from './fileA'",
124
+ filename: "./src/fileB.js",
125
+ options: [
126
+ {
127
+ imports: [
128
+ {
129
+ import: { member: ["foo"], from: "**/src/fileA" },
130
+ allow: ["**/src/**/*.test.js"],
131
+ },
132
+ ],
133
+ },
134
+ ],
135
+ errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
136
+ },
137
+ {
138
+ code: "import { foo } from './fileA'",
139
+ filename: "./src/fileB.js",
140
+ options: [
141
+ {
142
+ imports: [
143
+ {
144
+ import: { member: ["foo"], from: "**/src/fileA" },
145
+ disallow: ["**/src/**/*.js"],
146
+ },
147
+ ],
148
+ },
149
+ ],
150
+ errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
151
+ },
152
+ {
153
+ code: "import { foo } from './fileA'",
154
+ filename: "./src/fileB.js",
155
+ options: [
156
+ {
157
+ imports: [
158
+ {
159
+ import: { member: ["foo"], from: "**/src/fileA" },
160
+ allow: ["**/src/**/*.js"],
161
+ disallow: ["**/src/**/fileB.*"],
162
+ },
163
+ ],
164
+ },
165
+ ],
166
+ errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
167
+ },
168
+ {
169
+ code: "import foo from './fileA'",
170
+ filename: "./src/fileB.js",
171
+ options: [
172
+ {
173
+ imports: [
174
+ {
175
+ import: { member: ["default"], from: "**/src/fileA" },
176
+ disallow: ["**/src/**/*.js"],
177
+ },
178
+ ],
179
+ },
180
+ ],
181
+ errors: [{ messageId: "no-disallowed-imports", data: { member: "foo" } }],
182
+ },
183
+ ],
184
+ });