eslint-plugin-strict-dependencies 1.1.0 → 1.2.1

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # eslint-plugin-strict-dependencies
2
2
 
3
- ESlint plugin to define custom module dependency rules.
3
+ ESLint plugin to define custom module dependency rules.
4
4
 
5
5
  NOTE: `eslint-plugin-strict-dependencies` uses tsconfig, tsconfig.json must be present.
6
6
 
@@ -14,7 +14,10 @@ npm install eslint-plugin-strict-dependencies --save-dev
14
14
 
15
15
  - strict-dependencies
16
16
  - module: `string` (Glob or Forward matching string)
17
- - target module path
17
+ - Target module path
18
+ - targetMembers: `string[]`
19
+ - Target member name
20
+ - e.x. `["Suspense"]` in `import { Suspense } from 'react'`
18
21
  - allowReferenceFrom: `string[]` (Glob or Forward matching string)
19
22
  - Paths of files where target module imports are allowed.
20
23
  - allowSameModule: `boolean`
@@ -84,6 +87,17 @@ npm install eslint-plugin-strict-dependencies --save-dev
84
87
  "allowReferenceFrom": ["src/libs/router.ts"],
85
88
  "allowSameModule": false
86
89
  },
90
+
91
+ /**
92
+ * example:
93
+ * Disallow to import Suspense from react. it should always be imported using `libs/react.ts`.
94
+ */
95
+ {
96
+ "module": "react",
97
+ "targetMembers": ["Suspense"],
98
+ "allowReferenceFrom": ["src/libs/react.ts"],
99
+ "allowSameModule": false
100
+ },
87
101
  ],
88
102
  // options
89
103
  // {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-strict-dependencies",
3
3
  "description": "ESlint plugin to define custom module dependency rules.",
4
- "version": "1.1.0",
4
+ "version": "1.2.1",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/knowledge-work/eslint-plugin-strict-dependencies.git"
@@ -25,13 +25,13 @@
25
25
  "index.js"
26
26
  ],
27
27
  "dependencies": {
28
- "is-glob": "^4.0.3",
29
- "micromatch": "^4.0.4",
30
- "normalize-path": "^3.0.0",
31
- "require-strip-json-comments": "^2.0.0"
28
+ "is-glob": "4.0.3",
29
+ "micromatch": "4.0.5",
30
+ "normalize-path": "3.0.0",
31
+ "require-strip-json-comments": "2.0.0"
32
32
  },
33
33
  "devDependencies": {
34
- "jest": "^27.2.4"
34
+ "jest": "29.6.2"
35
35
  },
36
36
  "scripts": {
37
37
  "test": "jest --coverage",
@@ -68,19 +68,42 @@ module.exports = {
68
68
  const relativeFilePath = normalize(path.relative(process.cwd(), fileFullPath))
69
69
  const importPath = resolveImportPath(node.source.value, resolveRelativeImport ? relativeFilePath : null, pathIndexMap)
70
70
 
71
+ // specにはImportDefaultSpecifier/ImportNamespaceSpecifier/ImportSpecifierがあり、ImportSpecifierの場合はimportedが存在する
72
+ const importedModules = node.specifiers.filter(spec => 'imported' in spec).map(spec => spec.imported.name)
73
+
71
74
  dependencies
72
- .filter((dependency) => isMatch(importPath, dependency.module))
73
75
  .forEach((dependency) => {
74
- const isAllowed =
75
- // 参照元が許可されている
76
- dependency.allowReferenceFrom.some((allowPath) =>
77
- isMatch(relativeFilePath, allowPath),
78
- ) || // または同一モジュール間の参照が許可されている場合
79
- (dependency.allowSameModule && isMatch(relativeFilePath, dependency.module))
76
+ // そもそもmoduleがimportPathと一致していない場合は必ず報告しない
77
+ if (!isMatch(importPath, dependency.module)) return;
78
+
79
+ /**
80
+ * 1. 参照元チェックをしてAllowであればそこで処理を終了する
81
+ * 2. targetMembersが指定されていれば、targetMembersと実際にimportしているモジュールを比較して含まれていればエラーレポートして処理を終了する
82
+ * 3. targetMembersが指定されていない場合は、エラー扱いなのでエラーレポートして処理を終了する
83
+ */
84
+
85
+ const isAllowedByPath =
86
+ // 参照元が許可されている
87
+ dependency.allowReferenceFrom.some((allowPath) =>
88
+ isMatch(relativeFilePath, allowPath),
89
+ ) || // または同一モジュール間の参照が許可されている場合
90
+ (dependency.allowSameModule && isMatch(relativeFilePath, dependency.module))
80
91
 
81
- if (!isAllowed) {
82
- context.report(node, `import '${importPath}' is not allowed from ${relativeFilePath}.`)
92
+ if (isAllowedByPath) return
93
+
94
+ // importedされた値・型名もLintのターゲットに入っている場合の検出処理
95
+ function getCommonElements(arrA, arrB) {
96
+ return arrA.filter(element => arrB.includes(element));
97
+ }
98
+ if (dependency.targetMembers && Array.isArray(dependency.targetMembers)) {
99
+ const commonImportedList = getCommonElements(dependency.targetMembers, importedModules)
100
+ if (commonImportedList.length > 0) {
101
+ context.report(node, `import specifier '${commonImportedList.join(', ')}' is not allowed from ${relativeFilePath}.`)
102
+ }
103
+ return;
83
104
  }
105
+
106
+ context.report(node, `import '${importPath}' is not allowed from ${relativeFilePath}.`)
84
107
  })
85
108
  }
86
109