Skip to content

Commit 6331ef5

Browse files
authored
Merge branch 'main' into dependabot/npm_and_yarn/eslint/js-9.34.0
2 parents a78ed55 + 815b7a7 commit 6331ef5

File tree

16 files changed

+324
-138
lines changed

16 files changed

+324
-138
lines changed

.github/workflows/code_health.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
runs-on: ${{ matrix.os }}
2020
steps:
2121
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
22-
if: matrix.os != 'windows-latest'
22+
if: matrix.os == 'ubuntu-latest'
2323
- uses: actions/checkout@v5
2424
- uses: actions/setup-node@v4
2525
with:

.github/workflows/code_health_fork.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
runs-on: ${{ matrix.os }}
1919
steps:
2020
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
21-
if: matrix.os != 'windows-latest'
21+
if: matrix.os == 'ubuntu-latest'
2222
- uses: actions/checkout@v5
2323
- uses: actions/setup-node@v4
2424
with:

eslint-rules/no-config-imports.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"use strict";
2+
import path from "path";
3+
4+
// The file from which we wish to discourage importing values
5+
const configFilePath = path.resolve(import.meta.dirname, "../src/common/config.js");
6+
7+
// Files that are allowed to import value exports from config.ts
8+
const allowedConfigValueImportFiles = [
9+
// Main entry point that injects the config
10+
"src/index.ts",
11+
// Config resource definition that works with the some config values
12+
"src/resources/common/config.ts",
13+
];
14+
15+
// Ref: https://eslint.org/docs/latest/extend/custom-rules
16+
export default {
17+
meta: {
18+
type: "problem",
19+
docs: {
20+
description:
21+
"Disallows value imports from config.ts, with a few exceptions, to enforce dependency injection of the config.",
22+
recommended: true,
23+
},
24+
fixable: null,
25+
messages: {
26+
noConfigImports:
27+
"Value imports from config.ts are not allowed. Use dependency injection instead. Only type imports are permitted.",
28+
},
29+
},
30+
create(context) {
31+
const currentFilePath = path.resolve(context.getFilename());
32+
33+
const isCurrentFileAllowedToImport = allowedConfigValueImportFiles.some((allowedFile) => {
34+
const resolvedAllowedFile = path.resolve(allowedFile);
35+
return currentFilePath === resolvedAllowedFile;
36+
});
37+
38+
if (isCurrentFileAllowedToImport) {
39+
return {};
40+
}
41+
42+
return {
43+
ImportDeclaration(node) {
44+
const importPath = node.source.value;
45+
46+
// If the path is not relative, very likely its targeting a
47+
// node_module so we skip it. And also if the entire import is
48+
// marked with a type keyword.
49+
if (typeof importPath !== "string" || !importPath.startsWith(".") || node.importKind === "type") {
50+
return;
51+
}
52+
53+
const currentDir = path.dirname(currentFilePath);
54+
const resolvedImportPath = path.resolve(currentDir, importPath);
55+
56+
if (resolvedImportPath === configFilePath) {
57+
const hasValueImportFromConfig = node.specifiers.some((specifier) => {
58+
return specifier.importKind !== "type";
59+
});
60+
61+
if (hasValueImportFromConfig) {
62+
context.report({
63+
node,
64+
messageId: "noConfigImports",
65+
});
66+
}
67+
}
68+
},
69+
};
70+
},
71+
};
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import path from "path";
2+
import { RuleTester } from "eslint";
3+
import { describe, it } from "vitest";
4+
import tsParser from "@typescript-eslint/parser";
5+
import rule from "./no-config-imports.js";
6+
7+
const ROOT = process.cwd();
8+
const resolve = (p) => path.resolve(ROOT, p);
9+
10+
const ruleTester = new RuleTester({
11+
languageOptions: {
12+
parser: tsParser,
13+
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
14+
},
15+
});
16+
17+
describe("no-config-imports", () => {
18+
it("should not report any violations", () => {
19+
ruleTester.run("no-config-imports", rule, {
20+
valid: [
21+
{
22+
filename: resolve("src/some/module.ts"),
23+
code: 'import type { UserConfig } from "../common/config.js";\n',
24+
},
25+
{
26+
filename: resolve("src/some/module.ts"),
27+
code: 'import { something } from "../common/logger.js";\n',
28+
},
29+
{
30+
filename: resolve("src/some/module.ts"),
31+
code: 'import type * as Cfg from "../common/config.js";\n',
32+
},
33+
{
34+
filename: resolve("src/index.ts"),
35+
code: 'import { driverOptions } from "../common/config.js";\n',
36+
},
37+
],
38+
invalid: [],
39+
});
40+
});
41+
42+
it("should report rule violations", () => {
43+
ruleTester.run("no-config-imports", rule, {
44+
valid: [],
45+
invalid: [
46+
{
47+
filename: resolve("src/another/module.ts"),
48+
code: 'import { driverOptions } from "../common/config.js";\n',
49+
errors: [{ messageId: "noConfigImports" }],
50+
},
51+
{
52+
filename: resolve("src/another/module.ts"),
53+
code: 'import configDefault from "../common/config.js";\n',
54+
errors: [{ messageId: "noConfigImports" }],
55+
},
56+
{
57+
filename: resolve("src/another/module.ts"),
58+
code: 'import * as cfg from "../common/config.js";\n',
59+
errors: [{ messageId: "noConfigImports" }],
60+
},
61+
{
62+
filename: resolve("src/another/module.ts"),
63+
code: 'import { type UserConfig, driverOptions } from "../common/config.js";\n',
64+
errors: [{ messageId: "noConfigImports" }],
65+
},
66+
],
67+
});
68+
});
69+
});

eslint.config.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import path from "path";
12
import { defineConfig, globalIgnores } from "eslint/config";
23
import js from "@eslint/js";
34
import globals from "globals";
45
import tseslint from "typescript-eslint";
56
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
67
import vitestPlugin from "@vitest/eslint-plugin";
8+
import noConfigImports from "./eslint-rules/no-config-imports.js";
79

810
const testFiles = ["tests/**/*.test.ts", "tests/**/*.ts"];
911

@@ -62,6 +64,19 @@ export default defineConfig([
6264
"@typescript-eslint/explicit-function-return-type": "error",
6365
},
6466
},
67+
{
68+
files: ["src/**/*.ts"],
69+
plugins: {
70+
"no-config-imports": {
71+
rules: {
72+
"no-config-imports": noConfigImports,
73+
},
74+
},
75+
},
76+
rules: {
77+
"no-config-imports/no-config-imports": "error",
78+
},
79+
},
6580
globalIgnores([
6681
"node_modules",
6782
"dist",
@@ -72,6 +87,7 @@ export default defineConfig([
7287
"vitest.config.ts",
7388
"src/types/*.d.ts",
7489
"tests/integration/fixtures/",
90+
"eslint-rules",
7591
]),
7692
eslintPluginPrettierRecommended,
7793
]);

0 commit comments

Comments
 (0)