-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ESLint rule that enforces absolute (@src/...) imports from other …
…modules (#1303) Main motivation was to have nicer import paths for CRUD generator code It should avoid `import xxx from "../common/xxx";` and change it to `@src/common/xxx` For other examples see packages/eslint-plugin/src/rules/no-other-module-relative-import.test.ts very basic definition of "module" (a concept that doesn't really exist): - src/modulea - src/moduleb sub-modules or nested modules are not supported by this.
- Loading branch information
Showing
25 changed files
with
176 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
"@comet/eslint-plugin": minor | ||
--- | ||
|
||
Add new ESLint rule to enforce absolute imports when importing from other modules | ||
|
||
For instance, an import `import { AThingInModuleA } from "../moduleA/AThingInModuleA"` in module `B` needs to be imported as `import { AThingInModuleA } from "@src/moduleA/AThingInModuleA"`. | ||
The default source root `"./src"` and alias `"@src"` can be changed via the rule's `sourceRoot` and `sourceRootAlias` options. | ||
This rule will be enforced by `@comet/eslint-config` in the next major release. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/react", | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"] | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/react", | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"] | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/react", | ||
"ignorePatterns": ["src/*.generated.ts", "src/generated/", "lib/**"] | ||
"ignorePatterns": ["src/*.generated.ts", "src/generated/", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/react", | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"] | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/react", | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"] | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/react", | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"] | ||
"ignorePatterns": ["src/*.generated.ts", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/react", | ||
"ignorePatterns": ["src/**/*.generated.ts", "lib/**"] | ||
"ignorePatterns": ["src/**/*.generated.ts", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/nestjs", | ||
"ignorePatterns": ["lib/**"] | ||
"ignorePatterns": ["lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/nestjs", | ||
"ignorePatterns": ["src/mikro-orm/migrations/**", "lib/**"] | ||
"ignorePatterns": ["src/mikro-orm/migrations/**", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
{ | ||
"extends": "@comet/eslint-config/core", | ||
"ignorePatterns": ["bin/", "lib/**"] | ||
"ignorePatterns": ["bin/", "lib/**"], | ||
"rules": { | ||
"@comet/no-other-module-relative-import": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
packages/eslint-plugin/src/rules/no-other-module-relative-import.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { RuleTester } from "eslint"; | ||
|
||
import noOtherModuleRelativeImport from "./no-other-module-relative-import"; | ||
|
||
const ruleTester = new RuleTester({ | ||
parser: require.resolve("@typescript-eslint/parser"), | ||
}); | ||
|
||
const errors = [{ message: "Avoid relative import from other module" }]; | ||
|
||
const options = [{ sourceRoot: "./src", sourceRootAlias: "@src" }]; | ||
|
||
ruleTester.run("no-other-module-relative-import", noOtherModuleRelativeImport, { | ||
valid: [ | ||
{ | ||
code: `import Bar from "@src/moduleb/Bar";`, | ||
filename: `${process.cwd()}/src/modulea/Foo.ts`, | ||
options, | ||
}, | ||
{ code: `import Bar from "../Bar";`, filename: `${process.cwd()}/src/modulea/sub/Foo.ts`, options }, | ||
{ code: `import Bar from "xx/bar";`, filename: `${process.cwd()}/src/modulea/Foo.ts`, options }, | ||
], | ||
|
||
invalid: [ | ||
{ | ||
code: `import Bar from "../moduleb/Bar";`, | ||
filename: `${process.cwd()}/src/modulea/Foo.ts`, | ||
options, | ||
errors, | ||
output: `import Bar from "@src/moduleb/Bar";`, | ||
}, | ||
{ | ||
code: `import Bar from "../../Bar";`, | ||
filename: `${process.cwd()}/src/modulea/sub/Foo.ts`, | ||
options, | ||
errors, | ||
output: `import Bar from "@src/Bar";`, | ||
}, | ||
], | ||
}); |
68 changes: 68 additions & 0 deletions
68
packages/eslint-plugin/src/rules/no-other-module-relative-import.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { Rule } from "eslint"; | ||
import path from "path"; | ||
|
||
function parentDirCount(dir: string) { | ||
const match = dir.match(/^(\.\.\/)*/); | ||
return match[0].length / 3; | ||
} | ||
|
||
export default { | ||
meta: { | ||
type: "suggestion", | ||
fixable: "code", | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: { | ||
sourceRoot: { | ||
type: "string", | ||
}, | ||
sourceRootAlias: { | ||
type: "string", | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
create(context) { | ||
return { | ||
ImportDeclaration: function (node) { | ||
const options = context.options[0] ?? { sourceRoot: "./src", sourceRootAlias: "@src" }; | ||
|
||
const importParentDirCount = parentDirCount(node.source.value.toString()); | ||
if (!importParentDirCount) { | ||
// import is not relative | ||
return; | ||
} | ||
|
||
const filePath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(); | ||
if (filePath == "<text>") return; // If the input is from stdin, this test can't fail | ||
const sourceDir = `${context.getCwd()}/${options.sourceRoot}`; | ||
|
||
const fileDir = path.dirname(filePath); | ||
|
||
const relativeFileToSourceDir = path.relative(sourceDir, fileDir); | ||
if (!relativeFileToSourceDir || relativeFileToSourceDir.startsWith("..")) { | ||
// file is not in source directory | ||
return; | ||
} | ||
|
||
const fileSubdirectoriesCount = relativeFileToSourceDir.split(path.sep).length; | ||
|
||
// importParentDirCount is the number of ../ parts in the import path | ||
// fileSubdirectoriesCount is the number of subdirectories in the file path relative to the source directory | ||
if (importParentDirCount >= fileSubdirectoriesCount) { | ||
context.report({ | ||
node, | ||
message: "Avoid relative import from other module", | ||
fix: (fixer) => { | ||
const importPathRelativeToSourceDir = path.relative(sourceDir, `${fileDir}/${node.source.value.toString()}`); | ||
return fixer.replaceText(node.source, `"${options.sourceRootAlias}/${importPathRelativeToSourceDir}"`); | ||
}, | ||
}); | ||
} | ||
}, | ||
}; | ||
}, | ||
} as Rule.RuleModule; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters