diff --git a/scm-ui/eslint-config/src/__resources__/AllowRootImport.tsx b/scm-ui/eslint-config/src/__resources__/AllowRootImport.tsx
new file mode 100644
index 0000000000..c2a8396f93
--- /dev/null
+++ b/scm-ui/eslint-config/src/__resources__/AllowRootImport.tsx
@@ -0,0 +1,6 @@
+import React, { FC } from "react";
+import { Button } from "@scm-manager/ui-components";
+
+const SpecialButton: FC = () => ;
+
+export default SpecialButton;
diff --git a/scm-ui/eslint-config/src/__resources__/AvoidSourceImport.tsx b/scm-ui/eslint-config/src/__resources__/AvoidSourceImport.tsx
new file mode 100644
index 0000000000..75be029f6a
--- /dev/null
+++ b/scm-ui/eslint-config/src/__resources__/AvoidSourceImport.tsx
@@ -0,0 +1,6 @@
+import React, { FC } from "react";
+import Button from "@scm-manager/ui-components/src/buttons/Button";
+
+const SpecialButton: FC = () => ;
+
+export default SpecialButton;
diff --git a/scm-ui/eslint-config/src/index.js b/scm-ui/eslint-config/src/index.js
index 625e5bfb55..ac998d81fb 100644
--- a/scm-ui/eslint-config/src/index.js
+++ b/scm-ui/eslint-config/src/index.js
@@ -37,6 +37,10 @@ const nodeConfiguration = {
}
};
+const restrictImportConfig = {
+ patterns: ["@scm-manager/*/*"]
+};
+
const typescriptConfiguration = {
parser: "@typescript-eslint/parser",
extends: ["react-app", "plugin:@typescript-eslint/recommended"],
@@ -45,6 +49,7 @@ const typescriptConfiguration = {
"@typescript-eslint/ban-ts-ignore": "warn",
"no-console": "error",
"jsx-a11y/href-no-hash": "off",
+ "no-restricted-imports": ["error", restrictImportConfig],
...rules
}
};
diff --git a/scm-ui/eslint-config/src/index.test.js b/scm-ui/eslint-config/src/index.test.js
index 55af7ace6f..99acf09da9 100644
--- a/scm-ui/eslint-config/src/index.test.js
+++ b/scm-ui/eslint-config/src/index.test.js
@@ -25,27 +25,27 @@
const { ESLint } = require("eslint");
const path = require("path");
-describe("should lint files", () => {
- const eslint = new ESLint();
- const resource = path.join(__dirname, "__resources__");
+const eslint = new ESLint();
+const resource = path.join(__dirname, "__resources__");
- const lint = async file => {
- const results = await eslint.lintFiles([path.join(resource, file)]);
+const lint = async file => {
+ const results = await eslint.lintFiles([path.join(resource, file)]);
- const { messages } = results[0];
+ const { messages } = results[0];
- const warnings = messages.filter(m => m.severity === 1).map(m => m.ruleId);
- const errors = messages.filter(m => m.severity === 2).map(m => m.ruleId);
- return {
- errors,
- warnings
- };
+ const warnings = messages.filter(m => m.severity === 1).map(m => m.ruleId);
+ const errors = messages.filter(m => m.severity === 2).map(m => m.ruleId);
+ return {
+ errors,
+ warnings
};
+};
- const expectContains = (results, ...ids) => {
- ids.forEach(id => expect(results).toContain(id));
- };
+const expectContains = (results, ...ids) => {
+ ids.forEach(id => expect(results).toContain(id));
+};
+describe("should lint different file types", () => {
it("should lint tsx files", async () => {
const { errors, warnings } = await lint("TypescriptWithJsx.tsx");
expectContains(errors, "no-console", "quotes", "semi");
@@ -64,3 +64,16 @@ describe("should lint files", () => {
expectContains(warnings, "prettier/prettier");
});
});
+
+describe("lint @scm-manager imports", () => {
+ it("should return an error for source imports", async () => {
+ const { errors } = await lint("AvoidSourceImport.tsx");
+ expectContains(errors, "no-restricted-imports");
+ });
+
+ it("should return no error for package imports", async () => {
+ const { errors, warnings } = await lint("AllowRootImport.tsx");
+ expect(errors).toEqual([]);
+ expect(warnings).toEqual([]);
+ });
+});