@code-pushup/eslint-plugin 0.53.1 → 0.55.0
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 +6 -0
- package/bin.js +50 -76
- package/index.js +253 -121
- package/package.json +5 -5
- package/src/lib/config.d.ts +19 -20
- package/src/lib/meta/groups.d.ts +1 -1
- package/src/lib/meta/parse.d.ts +12 -0
- package/src/lib/meta/rules.d.ts +1 -10
- package/src/lib/meta/transform.d.ts +1 -1
- package/src/lib/meta/versions/detect.d.ts +2 -0
- package/src/lib/meta/versions/flat.d.ts +3 -0
- package/src/lib/meta/versions/formats.d.ts +1 -0
- package/src/lib/meta/versions/index.d.ts +6 -0
- package/src/lib/meta/versions/legacy.d.ts +3 -0
- package/src/lib/nx/filter-project-graph.d.ts +2 -0
- package/src/lib/nx/find-all-projects.d.ts +10 -3
- package/src/lib/setup.d.ts +1 -1
package/README.md
CHANGED
|
@@ -72,6 +72,12 @@ Detected ESLint rules are mapped to Code PushUp audits. Audit reports are calcul
|
|
|
72
72
|
};
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
You can also exclude specific projects if needed by passing their names in the `exclude` option:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
await eslintConfigFromAllNxProjects({ exclude: ['server'] });
|
|
79
|
+
```
|
|
80
|
+
|
|
75
81
|
- If you wish to target a specific project along with other projects it depends on, use the `eslintConfigFromNxProjectAndDeps` helper and pass in in your project name:
|
|
76
82
|
|
|
77
83
|
```js
|
package/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// packages/plugin-eslint/src/lib/runner/index.ts
|
|
2
|
-
import { writeFile
|
|
3
|
-
import { dirname, join as
|
|
2
|
+
import { writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
4
4
|
|
|
5
5
|
// packages/models/src/lib/implementation/schemas.ts
|
|
6
6
|
import { MATERIAL_ICONS } from "vscode-material-icons";
|
|
@@ -33,7 +33,7 @@ function exists(value) {
|
|
|
33
33
|
return value != null;
|
|
34
34
|
}
|
|
35
35
|
function getMissingRefsForCategories(categories, plugins) {
|
|
36
|
-
if (categories.length === 0) {
|
|
36
|
+
if (!categories || categories.length === 0) {
|
|
37
37
|
return false;
|
|
38
38
|
}
|
|
39
39
|
const auditRefsFromCategory = categories.flatMap(
|
|
@@ -110,7 +110,6 @@ var fileNameSchema = z.string().trim().regex(filenameRegex, {
|
|
|
110
110
|
message: `The filename has to be valid`
|
|
111
111
|
}).min(1, { message: "file name is invalid" });
|
|
112
112
|
var positiveIntSchema = z.number().int().positive();
|
|
113
|
-
var nonnegativeIntSchema = z.number().int().nonnegative();
|
|
114
113
|
var nonnegativeNumberSchema = z.number().nonnegative();
|
|
115
114
|
function packageVersionSchema(options) {
|
|
116
115
|
const { versionDescription = "NPM version of the package", required } = options ?? {};
|
|
@@ -533,12 +532,9 @@ var unrefinedCoreConfigSchema = z14.object({
|
|
|
533
532
|
var coreConfigSchema = refineCoreConfig(unrefinedCoreConfigSchema);
|
|
534
533
|
function refineCoreConfig(schema) {
|
|
535
534
|
return schema.refine(
|
|
536
|
-
(
|
|
537
|
-
(
|
|
538
|
-
message: missingRefsForCategoriesErrorMsg(
|
|
539
|
-
coreCfg.categories ?? [],
|
|
540
|
-
coreCfg.plugins
|
|
541
|
-
)
|
|
535
|
+
({ categories, plugins }) => !getMissingRefsForCategories(categories, plugins),
|
|
536
|
+
({ categories, plugins }) => ({
|
|
537
|
+
message: missingRefsForCategoriesErrorMsg(categories, plugins)
|
|
542
538
|
})
|
|
543
539
|
);
|
|
544
540
|
}
|
|
@@ -590,19 +586,16 @@ var reportSchema = packageVersionSchema({
|
|
|
590
586
|
).merge(
|
|
591
587
|
z15.object(
|
|
592
588
|
{
|
|
593
|
-
categories: z15.array(categoryConfigSchema),
|
|
594
589
|
plugins: z15.array(pluginReportSchema).min(1),
|
|
590
|
+
categories: z15.array(categoryConfigSchema).optional(),
|
|
595
591
|
commit: commitSchema.describe("Git commit for which report was collected").nullable()
|
|
596
592
|
},
|
|
597
593
|
{ description: "Collect output data" }
|
|
598
594
|
)
|
|
599
595
|
).refine(
|
|
600
|
-
(
|
|
601
|
-
(
|
|
602
|
-
message: missingRefsForCategoriesErrorMsg(
|
|
603
|
-
report.categories,
|
|
604
|
-
report.plugins
|
|
605
|
-
)
|
|
596
|
+
({ categories, plugins }) => !getMissingRefsForCategories(categories, plugins),
|
|
597
|
+
({ categories, plugins }) => ({
|
|
598
|
+
message: missingRefsForCategoriesErrorMsg(categories, plugins)
|
|
606
599
|
})
|
|
607
600
|
);
|
|
608
601
|
|
|
@@ -654,7 +647,7 @@ var auditDiffSchema = scorableWithPluginDiffSchema.merge(
|
|
|
654
647
|
z16.object({
|
|
655
648
|
values: makeComparisonSchema(auditValueSchema).merge(
|
|
656
649
|
z16.object({
|
|
657
|
-
diff: z16.number().
|
|
650
|
+
diff: z16.number().describe("Value change (`values.after - values.before`)")
|
|
658
651
|
})
|
|
659
652
|
).describe("Audit `value` comparison"),
|
|
660
653
|
displayValues: makeComparisonSchema(auditDisplayValueSchema).describe(
|
|
@@ -747,6 +740,7 @@ function executeProcess(cfg) {
|
|
|
747
740
|
return new Promise((resolve, reject) => {
|
|
748
741
|
const spawnedProcess = spawn(command, args ?? [], {
|
|
749
742
|
shell: true,
|
|
743
|
+
windowsHide: true,
|
|
750
744
|
...options
|
|
751
745
|
});
|
|
752
746
|
let stdout = "";
|
|
@@ -780,7 +774,7 @@ function executeProcess(cfg) {
|
|
|
780
774
|
import { bold, gray } from "ansis";
|
|
781
775
|
import { bundleRequire } from "bundle-require";
|
|
782
776
|
import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
|
|
783
|
-
import { join } from "node:path";
|
|
777
|
+
import { dirname, join } from "node:path";
|
|
784
778
|
|
|
785
779
|
// packages/utils/src/lib/formatting.ts
|
|
786
780
|
function slugify(text) {
|
|
@@ -934,22 +928,24 @@ import { MarkdownDocument as MarkdownDocument4, md as md5 } from "build-md";
|
|
|
934
928
|
import { bold as bold4, cyan, cyanBright, green as green2, red } from "ansis";
|
|
935
929
|
|
|
936
930
|
// packages/plugin-eslint/src/lib/runner/lint.ts
|
|
937
|
-
import { rm as rm2, writeFile } from "node:fs/promises";
|
|
938
931
|
import { platform } from "node:os";
|
|
939
|
-
import { join as join2 } from "node:path";
|
|
940
932
|
|
|
941
933
|
// packages/plugin-eslint/src/lib/setup.ts
|
|
942
934
|
import { ESLint } from "eslint";
|
|
943
|
-
function setupESLint(eslintrc) {
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
baseConfig: eslintrc,
|
|
948
|
-
useEslintrc: false
|
|
949
|
-
},
|
|
935
|
+
async function setupESLint(eslintrc) {
|
|
936
|
+
const eslintConstructor = await loadESLint();
|
|
937
|
+
return new eslintConstructor({
|
|
938
|
+
overrideConfigFile: eslintrc,
|
|
950
939
|
errorOnUnmatchedPattern: false
|
|
951
940
|
});
|
|
952
941
|
}
|
|
942
|
+
async function loadESLint() {
|
|
943
|
+
const eslint = await import("eslint");
|
|
944
|
+
if ("loadESLint" in eslint && typeof eslint.loadESLint === "function") {
|
|
945
|
+
return await eslint.loadESLint();
|
|
946
|
+
}
|
|
947
|
+
return ESLint;
|
|
948
|
+
}
|
|
953
949
|
|
|
954
950
|
// packages/plugin-eslint/src/lib/runner/lint.ts
|
|
955
951
|
async function lint({
|
|
@@ -957,37 +953,35 @@ async function lint({
|
|
|
957
953
|
patterns
|
|
958
954
|
}) {
|
|
959
955
|
const results = await executeLint({ eslintrc, patterns });
|
|
960
|
-
const
|
|
956
|
+
const eslint = await setupESLint(eslintrc);
|
|
957
|
+
const ruleOptionsPerFile = await loadRuleOptionsPerFile(eslint, results);
|
|
961
958
|
return { results, ruleOptionsPerFile };
|
|
962
959
|
}
|
|
963
|
-
function executeLint({
|
|
960
|
+
async function executeLint({
|
|
964
961
|
eslintrc,
|
|
965
962
|
patterns
|
|
966
963
|
}) {
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
platform() === "win32" ? pattern : `'${pattern}'`
|
|
980
|
-
)
|
|
964
|
+
const { stdout } = await executeProcess({
|
|
965
|
+
command: "npx",
|
|
966
|
+
args: [
|
|
967
|
+
"eslint",
|
|
968
|
+
...eslintrc ? [`--config=${filePathToCliArg(eslintrc)}`] : [],
|
|
969
|
+
...typeof eslintrc === "object" ? ["--no-eslintrc"] : [],
|
|
970
|
+
"--no-error-on-unmatched-pattern",
|
|
971
|
+
"--format=json",
|
|
972
|
+
...toArray(patterns).map(
|
|
973
|
+
(pattern) => (
|
|
974
|
+
// globs need to be escaped on Unix
|
|
975
|
+
platform() === "win32" ? pattern : `'${pattern}'`
|
|
981
976
|
)
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
return JSON.parse(stdout);
|
|
977
|
+
)
|
|
978
|
+
],
|
|
979
|
+
ignoreExitCode: true,
|
|
980
|
+
cwd: process.cwd()
|
|
987
981
|
});
|
|
982
|
+
return JSON.parse(stdout);
|
|
988
983
|
}
|
|
989
|
-
function loadRuleOptionsPerFile(
|
|
990
|
-
const eslint = setupESLint(eslintrc);
|
|
984
|
+
function loadRuleOptionsPerFile(eslint, results) {
|
|
991
985
|
return results.reduce(async (acc, { filePath, messages }) => {
|
|
992
986
|
const filesMap = await acc;
|
|
993
987
|
const config = await eslint.calculateConfigForFile(
|
|
@@ -1011,24 +1005,6 @@ function loadRuleOptionsPerFile(eslintrc, results) {
|
|
|
1011
1005
|
};
|
|
1012
1006
|
}, Promise.resolve({}));
|
|
1013
1007
|
}
|
|
1014
|
-
async function withConfig(eslintrc, fn) {
|
|
1015
|
-
if (typeof eslintrc !== "object") {
|
|
1016
|
-
return fn(eslintrc);
|
|
1017
|
-
}
|
|
1018
|
-
const configPath = generateTempConfigPath();
|
|
1019
|
-
await writeFile(configPath, JSON.stringify(eslintrc));
|
|
1020
|
-
try {
|
|
1021
|
-
return await fn(configPath);
|
|
1022
|
-
} finally {
|
|
1023
|
-
await rm2(configPath);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
function generateTempConfigPath() {
|
|
1027
|
-
return join2(
|
|
1028
|
-
process.cwd(),
|
|
1029
|
-
`.eslintrc.${Math.random().toString().slice(2)}.json`
|
|
1030
|
-
);
|
|
1031
|
-
}
|
|
1032
1008
|
|
|
1033
1009
|
// packages/plugin-eslint/src/lib/meta/hash.ts
|
|
1034
1010
|
import { createHash } from "node:crypto";
|
|
@@ -1122,16 +1098,14 @@ function convertSeverity(severity) {
|
|
|
1122
1098
|
|
|
1123
1099
|
// packages/plugin-eslint/src/lib/runner/index.ts
|
|
1124
1100
|
var WORKDIR = pluginWorkDir("eslint");
|
|
1125
|
-
var RUNNER_OUTPUT_PATH =
|
|
1126
|
-
var PLUGIN_CONFIG_PATH =
|
|
1101
|
+
var RUNNER_OUTPUT_PATH = join2(WORKDIR, "runner-output.json");
|
|
1102
|
+
var PLUGIN_CONFIG_PATH = join2(
|
|
1127
1103
|
process.cwd(),
|
|
1128
1104
|
WORKDIR,
|
|
1129
1105
|
"plugin-config.json"
|
|
1130
1106
|
);
|
|
1131
1107
|
async function executeRunner() {
|
|
1132
|
-
const { slugs, targets } = await readJsonFile(
|
|
1133
|
-
PLUGIN_CONFIG_PATH
|
|
1134
|
-
);
|
|
1108
|
+
const { slugs, targets } = await readJsonFile(PLUGIN_CONFIG_PATH);
|
|
1135
1109
|
const linterOutputs = await targets.reduce(
|
|
1136
1110
|
async (acc, target) => [...await acc, await lint(target)],
|
|
1137
1111
|
Promise.resolve([])
|
|
@@ -1147,8 +1121,8 @@ async function executeRunner() {
|
|
|
1147
1121
|
details: { issues: [] }
|
|
1148
1122
|
}
|
|
1149
1123
|
);
|
|
1150
|
-
await ensureDirectoryExists(
|
|
1151
|
-
await
|
|
1124
|
+
await ensureDirectoryExists(dirname2(RUNNER_OUTPUT_PATH));
|
|
1125
|
+
await writeFile(RUNNER_OUTPUT_PATH, JSON.stringify(audits));
|
|
1152
1126
|
}
|
|
1153
1127
|
|
|
1154
1128
|
// packages/plugin-eslint/src/bin.ts
|
package/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// packages/plugin-eslint/src/lib/eslint-plugin.ts
|
|
2
|
-
import { dirname as
|
|
2
|
+
import { dirname as dirname3, join as join4 } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
|
|
5
5
|
// packages/plugin-eslint/package.json
|
|
6
6
|
var name = "@code-pushup/eslint-plugin";
|
|
7
|
-
var version = "0.
|
|
7
|
+
var version = "0.55.0";
|
|
8
8
|
|
|
9
9
|
// packages/plugin-eslint/src/lib/config.ts
|
|
10
10
|
import { z as z17 } from "zod";
|
|
@@ -40,7 +40,7 @@ function exists(value) {
|
|
|
40
40
|
return value != null;
|
|
41
41
|
}
|
|
42
42
|
function getMissingRefsForCategories(categories, plugins) {
|
|
43
|
-
if (categories.length === 0) {
|
|
43
|
+
if (!categories || categories.length === 0) {
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
46
46
|
const auditRefsFromCategory = categories.flatMap(
|
|
@@ -117,7 +117,6 @@ var fileNameSchema = z.string().trim().regex(filenameRegex, {
|
|
|
117
117
|
message: `The filename has to be valid`
|
|
118
118
|
}).min(1, { message: "file name is invalid" });
|
|
119
119
|
var positiveIntSchema = z.number().int().positive();
|
|
120
|
-
var nonnegativeIntSchema = z.number().int().nonnegative();
|
|
121
120
|
var nonnegativeNumberSchema = z.number().nonnegative();
|
|
122
121
|
function packageVersionSchema(options) {
|
|
123
122
|
const { versionDescription = "NPM version of the package", required } = options ?? {};
|
|
@@ -540,12 +539,9 @@ var unrefinedCoreConfigSchema = z14.object({
|
|
|
540
539
|
var coreConfigSchema = refineCoreConfig(unrefinedCoreConfigSchema);
|
|
541
540
|
function refineCoreConfig(schema) {
|
|
542
541
|
return schema.refine(
|
|
543
|
-
(
|
|
544
|
-
(
|
|
545
|
-
message: missingRefsForCategoriesErrorMsg(
|
|
546
|
-
coreCfg.categories ?? [],
|
|
547
|
-
coreCfg.plugins
|
|
548
|
-
)
|
|
542
|
+
({ categories, plugins }) => !getMissingRefsForCategories(categories, plugins),
|
|
543
|
+
({ categories, plugins }) => ({
|
|
544
|
+
message: missingRefsForCategoriesErrorMsg(categories, plugins)
|
|
549
545
|
})
|
|
550
546
|
);
|
|
551
547
|
}
|
|
@@ -597,19 +593,16 @@ var reportSchema = packageVersionSchema({
|
|
|
597
593
|
).merge(
|
|
598
594
|
z15.object(
|
|
599
595
|
{
|
|
600
|
-
categories: z15.array(categoryConfigSchema),
|
|
601
596
|
plugins: z15.array(pluginReportSchema).min(1),
|
|
597
|
+
categories: z15.array(categoryConfigSchema).optional(),
|
|
602
598
|
commit: commitSchema.describe("Git commit for which report was collected").nullable()
|
|
603
599
|
},
|
|
604
600
|
{ description: "Collect output data" }
|
|
605
601
|
)
|
|
606
602
|
).refine(
|
|
607
|
-
(
|
|
608
|
-
(
|
|
609
|
-
message: missingRefsForCategoriesErrorMsg(
|
|
610
|
-
report.categories,
|
|
611
|
-
report.plugins
|
|
612
|
-
)
|
|
603
|
+
({ categories, plugins }) => !getMissingRefsForCategories(categories, plugins),
|
|
604
|
+
({ categories, plugins }) => ({
|
|
605
|
+
message: missingRefsForCategoriesErrorMsg(categories, plugins)
|
|
613
606
|
})
|
|
614
607
|
);
|
|
615
608
|
|
|
@@ -661,7 +654,7 @@ var auditDiffSchema = scorableWithPluginDiffSchema.merge(
|
|
|
661
654
|
z16.object({
|
|
662
655
|
values: makeComparisonSchema(auditValueSchema).merge(
|
|
663
656
|
z16.object({
|
|
664
|
-
diff: z16.number().
|
|
657
|
+
diff: z16.number().describe("Value change (`values.after - values.before`)")
|
|
665
658
|
})
|
|
666
659
|
).describe("Audit `value` comparison"),
|
|
667
660
|
displayValues: makeComparisonSchema(auditDisplayValueSchema).describe(
|
|
@@ -720,7 +713,7 @@ var TERMINAL_WIDTH = 80;
|
|
|
720
713
|
import { bold, gray } from "ansis";
|
|
721
714
|
import { bundleRequire } from "bundle-require";
|
|
722
715
|
import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
|
|
723
|
-
import { join } from "node:path";
|
|
716
|
+
import { dirname, join } from "node:path";
|
|
724
717
|
|
|
725
718
|
// packages/utils/src/lib/formatting.ts
|
|
726
719
|
function slugify(text) {
|
|
@@ -803,6 +796,16 @@ async function ensureDirectoryExists(baseDir) {
|
|
|
803
796
|
function pluginWorkDir(slug) {
|
|
804
797
|
return join("node_modules", ".code-pushup", slug);
|
|
805
798
|
}
|
|
799
|
+
async function findNearestFile(fileNames, cwd = process.cwd()) {
|
|
800
|
+
for (let directory = cwd; directory !== dirname(directory); directory = dirname(directory)) {
|
|
801
|
+
for (const file of fileNames) {
|
|
802
|
+
if (await fileExists(join(directory, file))) {
|
|
803
|
+
return join(directory, file);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
return void 0;
|
|
808
|
+
}
|
|
806
809
|
function filePathToCliArg(path) {
|
|
807
810
|
return `"${path}"`;
|
|
808
811
|
}
|
|
@@ -859,15 +862,7 @@ import { bold as bold4, cyan, cyanBright, green as green2, red } from "ansis";
|
|
|
859
862
|
var patternsSchema = z17.union([z17.string(), z17.array(z17.string()).min(1)], {
|
|
860
863
|
description: "Lint target files. May contain file paths, directory paths or glob patterns"
|
|
861
864
|
});
|
|
862
|
-
var eslintrcSchema = z17.
|
|
863
|
-
[
|
|
864
|
-
z17.string({ description: "Path to ESLint config file" }),
|
|
865
|
-
z17.record(z17.string(), z17.unknown(), {
|
|
866
|
-
description: "ESLint config object"
|
|
867
|
-
})
|
|
868
|
-
],
|
|
869
|
-
{ description: "ESLint config as file path or inline object" }
|
|
870
|
-
);
|
|
865
|
+
var eslintrcSchema = z17.string({ description: "Path to ESLint config file" });
|
|
871
866
|
var eslintTargetObjectSchema = z17.object({
|
|
872
867
|
eslintrc: eslintrcSchema.optional(),
|
|
873
868
|
patterns: patternsSchema
|
|
@@ -890,80 +885,16 @@ function jsonHash(data, bytes = 8) {
|
|
|
890
885
|
return createHash("shake256", { outputLength: bytes }).update(JSON.stringify(data) || "null").digest("hex");
|
|
891
886
|
}
|
|
892
887
|
|
|
893
|
-
// packages/plugin-eslint/src/lib/
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
// packages/plugin-eslint/src/lib/meta/rules.ts
|
|
907
|
-
async function listRules(targets) {
|
|
908
|
-
const rulesMap = await targets.reduce(async (acc, { eslintrc, patterns }) => {
|
|
909
|
-
const eslint = setupESLint(eslintrc);
|
|
910
|
-
const prev = await acc;
|
|
911
|
-
const curr = await loadRulesMap(eslint, patterns);
|
|
912
|
-
return mergeRulesMaps(prev, curr);
|
|
913
|
-
}, Promise.resolve({}));
|
|
914
|
-
return Object.values(rulesMap).flatMap(Object.values);
|
|
915
|
-
}
|
|
916
|
-
async function loadRulesMap(eslint, patterns) {
|
|
917
|
-
const configs = await toArray(patterns).reduce(
|
|
918
|
-
async (acc, pattern) => [
|
|
919
|
-
...await acc,
|
|
920
|
-
await eslint.calculateConfigForFile(pattern)
|
|
921
|
-
],
|
|
922
|
-
Promise.resolve([])
|
|
923
|
-
);
|
|
924
|
-
const rulesIds = distinct(
|
|
925
|
-
configs.flatMap((config) => Object.keys(config.rules ?? {}))
|
|
926
|
-
);
|
|
927
|
-
const rulesMeta = eslint.getRulesMetaForResults([
|
|
928
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
929
|
-
{
|
|
930
|
-
messages: rulesIds.map((ruleId) => ({ ruleId })),
|
|
931
|
-
suppressedMessages: []
|
|
932
|
-
}
|
|
933
|
-
]);
|
|
934
|
-
return configs.flatMap((config) => Object.entries(config.rules ?? {})).filter(([, ruleEntry]) => ruleEntry != null && !isRuleOff(ruleEntry)).reduce((acc, [ruleId, ruleEntry]) => {
|
|
935
|
-
const meta = rulesMeta[ruleId];
|
|
936
|
-
if (!meta) {
|
|
937
|
-
ui().logger.warning(`Metadata not found for ESLint rule ${ruleId}`);
|
|
938
|
-
return acc;
|
|
939
|
-
}
|
|
940
|
-
const options = toArray(ruleEntry).slice(1);
|
|
941
|
-
const optionsHash = jsonHash(options);
|
|
942
|
-
const ruleData = {
|
|
943
|
-
ruleId,
|
|
944
|
-
meta,
|
|
945
|
-
options
|
|
946
|
-
};
|
|
947
|
-
return {
|
|
948
|
-
...acc,
|
|
949
|
-
[ruleId]: {
|
|
950
|
-
...acc[ruleId],
|
|
951
|
-
[optionsHash]: ruleData
|
|
952
|
-
}
|
|
953
|
-
};
|
|
954
|
-
}, {});
|
|
955
|
-
}
|
|
956
|
-
function mergeRulesMaps(prev, curr) {
|
|
957
|
-
return Object.entries(curr).reduce(
|
|
958
|
-
(acc, [ruleId, ruleVariants]) => ({
|
|
959
|
-
...acc,
|
|
960
|
-
[ruleId]: {
|
|
961
|
-
...acc[ruleId],
|
|
962
|
-
...ruleVariants
|
|
963
|
-
}
|
|
964
|
-
}),
|
|
965
|
-
prev
|
|
966
|
-
);
|
|
888
|
+
// packages/plugin-eslint/src/lib/meta/parse.ts
|
|
889
|
+
function parseRuleId(ruleId) {
|
|
890
|
+
const i = ruleId.lastIndexOf("/");
|
|
891
|
+
if (i < 0) {
|
|
892
|
+
return { name: ruleId };
|
|
893
|
+
}
|
|
894
|
+
return {
|
|
895
|
+
plugin: ruleId.slice(0, i),
|
|
896
|
+
name: ruleId.slice(i + 1)
|
|
897
|
+
};
|
|
967
898
|
}
|
|
968
899
|
function isRuleOff(entry) {
|
|
969
900
|
const level = Array.isArray(entry) ? entry[0] : entry;
|
|
@@ -978,15 +909,8 @@ function isRuleOff(entry) {
|
|
|
978
909
|
return false;
|
|
979
910
|
}
|
|
980
911
|
}
|
|
981
|
-
function
|
|
982
|
-
|
|
983
|
-
if (i < 0) {
|
|
984
|
-
return { name: ruleId };
|
|
985
|
-
}
|
|
986
|
-
return {
|
|
987
|
-
plugin: ruleId.slice(0, i),
|
|
988
|
-
name: ruleId.slice(i + 1)
|
|
989
|
-
};
|
|
912
|
+
function optionsFromRuleEntry(entry) {
|
|
913
|
+
return toArray(entry).slice(1);
|
|
990
914
|
}
|
|
991
915
|
|
|
992
916
|
// packages/plugin-eslint/src/lib/meta/groups.ts
|
|
@@ -1054,6 +978,191 @@ function groupsFromRuleCategories(rules) {
|
|
|
1054
978
|
return groups.toSorted((a, b) => a.slug.localeCompare(b.slug));
|
|
1055
979
|
}
|
|
1056
980
|
|
|
981
|
+
// packages/plugin-eslint/src/lib/meta/versions/flat.ts
|
|
982
|
+
import { builtinRules } from "eslint/use-at-your-own-risk";
|
|
983
|
+
import { isAbsolute, join as join2 } from "node:path";
|
|
984
|
+
import { pathToFileURL } from "node:url";
|
|
985
|
+
async function loadRulesForFlatConfig({
|
|
986
|
+
eslintrc
|
|
987
|
+
}) {
|
|
988
|
+
const config = eslintrc ? await loadConfigByPath(eslintrc) : await loadConfigByDefaultLocation();
|
|
989
|
+
const configs = toArray(config);
|
|
990
|
+
const rules = findEnabledRulesWithOptions(configs);
|
|
991
|
+
return rules.map((rule) => {
|
|
992
|
+
const meta = findRuleMeta(rule.ruleId, configs);
|
|
993
|
+
if (!meta) {
|
|
994
|
+
ui().logger.warning(`Cannot find metadata for rule ${rule.ruleId}`);
|
|
995
|
+
return null;
|
|
996
|
+
}
|
|
997
|
+
return { ...rule, meta };
|
|
998
|
+
}).filter(exists);
|
|
999
|
+
}
|
|
1000
|
+
async function loadConfigByDefaultLocation() {
|
|
1001
|
+
const flatConfigFileNames = [
|
|
1002
|
+
"eslint.config.js",
|
|
1003
|
+
"eslint.config.mjs",
|
|
1004
|
+
"eslint.config.cjs"
|
|
1005
|
+
];
|
|
1006
|
+
const configPath = await findNearestFile(flatConfigFileNames);
|
|
1007
|
+
if (configPath) {
|
|
1008
|
+
return loadConfigByPath(configPath);
|
|
1009
|
+
}
|
|
1010
|
+
throw new Error(
|
|
1011
|
+
[
|
|
1012
|
+
`ESLint config file not found - expected ${flatConfigFileNames.join("/")} in ${process.cwd()} or some parent directory`,
|
|
1013
|
+
"If your ESLint config is in a non-standard location, use the `eslintrc` parameter to specify the path."
|
|
1014
|
+
].join("\n")
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
async function loadConfigByPath(path) {
|
|
1018
|
+
const absolutePath = isAbsolute(path) ? path : join2(process.cwd(), path);
|
|
1019
|
+
const url = pathToFileURL(absolutePath).toString();
|
|
1020
|
+
const mod = await import(url);
|
|
1021
|
+
return "default" in mod ? mod.default : mod;
|
|
1022
|
+
}
|
|
1023
|
+
function findEnabledRulesWithOptions(configs) {
|
|
1024
|
+
const enabledRules = configs.flatMap(({ rules }) => Object.entries(rules ?? {})).filter(([, entry]) => entry != null && !isRuleOff(entry)).map(([ruleId, entry]) => ({
|
|
1025
|
+
ruleId,
|
|
1026
|
+
options: entry ? optionsFromRuleEntry(entry) : []
|
|
1027
|
+
}));
|
|
1028
|
+
const uniqueRulesMap = new Map(
|
|
1029
|
+
enabledRules.map(({ ruleId, options }) => [
|
|
1030
|
+
`${ruleId}::${jsonHash(options)}`,
|
|
1031
|
+
{ ruleId, options }
|
|
1032
|
+
])
|
|
1033
|
+
);
|
|
1034
|
+
return [...uniqueRulesMap.values()];
|
|
1035
|
+
}
|
|
1036
|
+
function findRuleMeta(ruleId, configs) {
|
|
1037
|
+
const { plugin, name: name2 } = parseRuleId(ruleId);
|
|
1038
|
+
if (!plugin) {
|
|
1039
|
+
return findBuiltinRuleMeta(name2);
|
|
1040
|
+
}
|
|
1041
|
+
return findPluginRuleMeta(plugin, name2, configs);
|
|
1042
|
+
}
|
|
1043
|
+
function findBuiltinRuleMeta(name2) {
|
|
1044
|
+
const rule = builtinRules.get(name2);
|
|
1045
|
+
return rule?.meta;
|
|
1046
|
+
}
|
|
1047
|
+
function findPluginRuleMeta(plugin, name2, configs) {
|
|
1048
|
+
const config = configs.find(({ plugins = {} }) => plugin in plugins);
|
|
1049
|
+
const rule = config?.plugins?.[plugin]?.rules?.[name2];
|
|
1050
|
+
if (typeof rule === "function") {
|
|
1051
|
+
ui().logger.warning(
|
|
1052
|
+
`Cannot parse metadata for rule ${plugin}/${name2}, plugin registers it as a function`
|
|
1053
|
+
);
|
|
1054
|
+
return void 0;
|
|
1055
|
+
}
|
|
1056
|
+
return rule?.meta;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
// packages/plugin-eslint/src/lib/setup.ts
|
|
1060
|
+
import { ESLint } from "eslint";
|
|
1061
|
+
async function setupESLint(eslintrc) {
|
|
1062
|
+
const eslintConstructor = await loadESLint();
|
|
1063
|
+
return new eslintConstructor({
|
|
1064
|
+
overrideConfigFile: eslintrc,
|
|
1065
|
+
errorOnUnmatchedPattern: false
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
async function loadESLint() {
|
|
1069
|
+
const eslint = await import("eslint");
|
|
1070
|
+
if ("loadESLint" in eslint && typeof eslint.loadESLint === "function") {
|
|
1071
|
+
return await eslint.loadESLint();
|
|
1072
|
+
}
|
|
1073
|
+
return ESLint;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
// packages/plugin-eslint/src/lib/meta/versions/legacy.ts
|
|
1077
|
+
async function loadRulesForLegacyConfig({
|
|
1078
|
+
eslintrc,
|
|
1079
|
+
patterns
|
|
1080
|
+
}) {
|
|
1081
|
+
const eslint = await setupESLint(eslintrc);
|
|
1082
|
+
const configs = await toArray(patterns).reduce(
|
|
1083
|
+
async (acc, pattern) => [
|
|
1084
|
+
...await acc,
|
|
1085
|
+
await eslint.calculateConfigForFile(pattern)
|
|
1086
|
+
],
|
|
1087
|
+
Promise.resolve([])
|
|
1088
|
+
);
|
|
1089
|
+
const rulesIds = distinct(
|
|
1090
|
+
configs.flatMap((config) => Object.keys(config.rules ?? {}))
|
|
1091
|
+
);
|
|
1092
|
+
const rulesMeta = eslint.getRulesMetaForResults([
|
|
1093
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
1094
|
+
{
|
|
1095
|
+
messages: rulesIds.map((ruleId) => ({ ruleId })),
|
|
1096
|
+
suppressedMessages: []
|
|
1097
|
+
}
|
|
1098
|
+
]);
|
|
1099
|
+
return configs.flatMap((config) => Object.entries(config.rules ?? {})).map(([ruleId, ruleEntry]) => {
|
|
1100
|
+
if (ruleEntry == null || isRuleOff(ruleEntry)) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
const meta = rulesMeta[ruleId];
|
|
1104
|
+
if (!meta) {
|
|
1105
|
+
ui().logger.warning(`Metadata not found for ESLint rule ${ruleId}`);
|
|
1106
|
+
return null;
|
|
1107
|
+
}
|
|
1108
|
+
const options = optionsFromRuleEntry(ruleEntry);
|
|
1109
|
+
return {
|
|
1110
|
+
ruleId,
|
|
1111
|
+
meta,
|
|
1112
|
+
options
|
|
1113
|
+
};
|
|
1114
|
+
}).filter(exists);
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
// packages/plugin-eslint/src/lib/meta/versions/detect.ts
|
|
1118
|
+
import { ESLint as ESLint2 } from "eslint";
|
|
1119
|
+
async function detectConfigVersion() {
|
|
1120
|
+
if (process.env["ESLINT_USE_FLAT_CONFIG"] === "true") {
|
|
1121
|
+
return "flat";
|
|
1122
|
+
}
|
|
1123
|
+
if (process.env["ESLINT_USE_FLAT_CONFIG"] === "false") {
|
|
1124
|
+
return "legacy";
|
|
1125
|
+
}
|
|
1126
|
+
if (ESLint2.version.startsWith("8.")) {
|
|
1127
|
+
if (await fileExists("eslint.config.js")) {
|
|
1128
|
+
return "flat";
|
|
1129
|
+
}
|
|
1130
|
+
return "legacy";
|
|
1131
|
+
}
|
|
1132
|
+
return "flat";
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// packages/plugin-eslint/src/lib/meta/versions/index.ts
|
|
1136
|
+
function selectRulesLoader(version2) {
|
|
1137
|
+
switch (version2) {
|
|
1138
|
+
case "flat":
|
|
1139
|
+
return loadRulesForFlatConfig;
|
|
1140
|
+
case "legacy":
|
|
1141
|
+
return loadRulesForLegacyConfig;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// packages/plugin-eslint/src/lib/meta/rules.ts
|
|
1146
|
+
async function listRules(targets) {
|
|
1147
|
+
const version2 = await detectConfigVersion();
|
|
1148
|
+
const loadRulesMap = selectRulesLoader(version2);
|
|
1149
|
+
const rulesMap = await targets.reduce(async (acc, target) => {
|
|
1150
|
+
const map = await acc;
|
|
1151
|
+
const rules = await loadRulesMap(target);
|
|
1152
|
+
return rules.reduce(mergeRuleIntoMap, map);
|
|
1153
|
+
}, Promise.resolve({}));
|
|
1154
|
+
return Object.values(rulesMap).flatMap(Object.values);
|
|
1155
|
+
}
|
|
1156
|
+
function mergeRuleIntoMap(map, rule) {
|
|
1157
|
+
return {
|
|
1158
|
+
...map,
|
|
1159
|
+
[rule.ruleId]: {
|
|
1160
|
+
...map[rule.ruleId],
|
|
1161
|
+
[jsonHash(rule.options)]: rule
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1057
1166
|
// packages/plugin-eslint/src/lib/meta/transform.ts
|
|
1058
1167
|
function ruleToAudit({ ruleId, meta, options }) {
|
|
1059
1168
|
const name2 = ruleId.split("/").at(-1) ?? ruleId;
|
|
@@ -1089,10 +1198,10 @@ async function listAuditsAndGroups(targets) {
|
|
|
1089
1198
|
|
|
1090
1199
|
// packages/plugin-eslint/src/lib/runner/index.ts
|
|
1091
1200
|
import { writeFile } from "node:fs/promises";
|
|
1092
|
-
import { dirname, join as
|
|
1201
|
+
import { dirname as dirname2, join as join3 } from "node:path";
|
|
1093
1202
|
var WORKDIR = pluginWorkDir("eslint");
|
|
1094
|
-
var RUNNER_OUTPUT_PATH =
|
|
1095
|
-
var PLUGIN_CONFIG_PATH =
|
|
1203
|
+
var RUNNER_OUTPUT_PATH = join3(WORKDIR, "runner-output.json");
|
|
1204
|
+
var PLUGIN_CONFIG_PATH = join3(
|
|
1096
1205
|
process.cwd(),
|
|
1097
1206
|
WORKDIR,
|
|
1098
1207
|
"plugin-config.json"
|
|
@@ -1102,7 +1211,7 @@ async function createRunnerConfig(scriptPath, audits, targets) {
|
|
|
1102
1211
|
targets,
|
|
1103
1212
|
slugs: audits.map((audit) => audit.slug)
|
|
1104
1213
|
};
|
|
1105
|
-
await ensureDirectoryExists(
|
|
1214
|
+
await ensureDirectoryExists(dirname2(PLUGIN_CONFIG_PATH));
|
|
1106
1215
|
await writeFile(PLUGIN_CONFIG_PATH, JSON.stringify(config));
|
|
1107
1216
|
return {
|
|
1108
1217
|
command: "node",
|
|
@@ -1115,8 +1224,8 @@ async function createRunnerConfig(scriptPath, audits, targets) {
|
|
|
1115
1224
|
async function eslintPlugin(config) {
|
|
1116
1225
|
const targets = eslintPluginConfigSchema.parse(config);
|
|
1117
1226
|
const { audits, groups } = await listAuditsAndGroups(targets);
|
|
1118
|
-
const runnerScriptPath =
|
|
1119
|
-
fileURLToPath(
|
|
1227
|
+
const runnerScriptPath = join4(
|
|
1228
|
+
fileURLToPath(dirname3(import.meta.url)),
|
|
1120
1229
|
"bin.js"
|
|
1121
1230
|
);
|
|
1122
1231
|
return {
|
|
@@ -1133,14 +1242,33 @@ async function eslintPlugin(config) {
|
|
|
1133
1242
|
};
|
|
1134
1243
|
}
|
|
1135
1244
|
|
|
1245
|
+
// packages/plugin-eslint/src/lib/nx/filter-project-graph.ts
|
|
1246
|
+
function filterProjectGraph(projectGraph, exclude = []) {
|
|
1247
|
+
const filteredNodes = Object.entries(
|
|
1248
|
+
projectGraph.nodes
|
|
1249
|
+
).reduce(
|
|
1250
|
+
(acc, [projectName, projectNode]) => exclude.includes(projectName) ? acc : { ...acc, [projectName]: projectNode },
|
|
1251
|
+
{}
|
|
1252
|
+
);
|
|
1253
|
+
const filteredDependencies = Object.entries(projectGraph.dependencies).reduce(
|
|
1254
|
+
(acc, [key, deps]) => exclude.includes(key) ? acc : { ...acc, [key]: deps },
|
|
1255
|
+
{}
|
|
1256
|
+
);
|
|
1257
|
+
return {
|
|
1258
|
+
nodes: filteredNodes,
|
|
1259
|
+
dependencies: filteredDependencies,
|
|
1260
|
+
version: projectGraph.version
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1136
1264
|
// packages/plugin-eslint/src/lib/nx/utils.ts
|
|
1137
|
-
import { join as
|
|
1265
|
+
import { join as join5 } from "node:path";
|
|
1138
1266
|
async function findCodePushupEslintrc(project) {
|
|
1139
1267
|
const name2 = "code-pushup.eslintrc";
|
|
1140
1268
|
const extensions = ["json", "js", "cjs", "yml", "yaml"];
|
|
1141
1269
|
for (const ext of extensions) {
|
|
1142
1270
|
const filename = `./${project.root}/${name2}.${ext}`;
|
|
1143
|
-
if (await fileExists(
|
|
1271
|
+
if (await fileExists(join5(process.cwd(), filename))) {
|
|
1144
1272
|
return filename;
|
|
1145
1273
|
}
|
|
1146
1274
|
}
|
|
@@ -1184,10 +1312,14 @@ async function nxProjectsToConfig(projectGraph, predicate = () => true) {
|
|
|
1184
1312
|
}
|
|
1185
1313
|
|
|
1186
1314
|
// packages/plugin-eslint/src/lib/nx/find-all-projects.ts
|
|
1187
|
-
async function eslintConfigFromAllNxProjects() {
|
|
1315
|
+
async function eslintConfigFromAllNxProjects(options = {}) {
|
|
1188
1316
|
const { createProjectGraphAsync } = await import("@nx/devkit");
|
|
1189
1317
|
const projectGraph = await createProjectGraphAsync({ exitOnError: false });
|
|
1190
|
-
|
|
1318
|
+
const filteredProjectGraph = filterProjectGraph(
|
|
1319
|
+
projectGraph,
|
|
1320
|
+
options.exclude
|
|
1321
|
+
);
|
|
1322
|
+
return nxProjectsToConfig(filteredProjectGraph);
|
|
1191
1323
|
}
|
|
1192
1324
|
var eslintConfigFromNxProjects = eslintConfigFromAllNxProjects;
|
|
1193
1325
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-pushup/eslint-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.55.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Code PushUp plugin for detecting problems in source code using ESLint.📋",
|
|
6
6
|
"homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-eslint#readme",
|
|
@@ -40,13 +40,13 @@
|
|
|
40
40
|
"main": "./index.js",
|
|
41
41
|
"types": "./src/index.d.ts",
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@code-pushup/utils": "0.
|
|
44
|
-
"@code-pushup/models": "0.
|
|
45
|
-
"eslint": "^8.46.0",
|
|
43
|
+
"@code-pushup/utils": "0.55.0",
|
|
44
|
+
"@code-pushup/models": "0.55.0",
|
|
46
45
|
"zod": "^3.22.4"
|
|
47
46
|
},
|
|
48
47
|
"peerDependencies": {
|
|
49
|
-
"@nx/devkit": "
|
|
48
|
+
"@nx/devkit": ">=17.0.0",
|
|
49
|
+
"eslint": "^8.46.0 || ^9.0.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependenciesMeta": {
|
|
52
52
|
"@nx/devkit": {
|
package/src/lib/config.d.ts
CHANGED
|
@@ -1,61 +1,60 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { type ZodType, z } from 'zod';
|
|
1
|
+
import { z } from 'zod';
|
|
3
2
|
export declare const eslintTargetSchema: z.ZodEffects<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
|
|
4
|
-
eslintrc: z.ZodOptional<z.
|
|
3
|
+
eslintrc: z.ZodOptional<z.ZodString>;
|
|
5
4
|
patterns: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
|
|
6
5
|
}, "strip", z.ZodTypeAny, {
|
|
7
6
|
patterns: string | string[];
|
|
8
|
-
eslintrc?: string |
|
|
7
|
+
eslintrc?: string | undefined;
|
|
9
8
|
}, {
|
|
10
9
|
patterns: string | string[];
|
|
11
|
-
eslintrc?: string |
|
|
10
|
+
eslintrc?: string | undefined;
|
|
12
11
|
}>]>, {
|
|
13
12
|
patterns: string | string[];
|
|
14
|
-
eslintrc?: string |
|
|
13
|
+
eslintrc?: string | undefined;
|
|
15
14
|
}, string | string[] | {
|
|
16
15
|
patterns: string | string[];
|
|
17
|
-
eslintrc?: string |
|
|
16
|
+
eslintrc?: string | undefined;
|
|
18
17
|
}>;
|
|
19
18
|
export type ESLintTarget = z.infer<typeof eslintTargetSchema>;
|
|
20
19
|
export declare const eslintPluginConfigSchema: z.ZodEffects<z.ZodUnion<[z.ZodEffects<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
|
|
21
|
-
eslintrc: z.ZodOptional<z.
|
|
20
|
+
eslintrc: z.ZodOptional<z.ZodString>;
|
|
22
21
|
patterns: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
|
|
23
22
|
}, "strip", z.ZodTypeAny, {
|
|
24
23
|
patterns: string | string[];
|
|
25
|
-
eslintrc?: string |
|
|
24
|
+
eslintrc?: string | undefined;
|
|
26
25
|
}, {
|
|
27
26
|
patterns: string | string[];
|
|
28
|
-
eslintrc?: string |
|
|
27
|
+
eslintrc?: string | undefined;
|
|
29
28
|
}>]>, {
|
|
30
29
|
patterns: string | string[];
|
|
31
|
-
eslintrc?: string |
|
|
30
|
+
eslintrc?: string | undefined;
|
|
32
31
|
}, string | string[] | {
|
|
33
32
|
patterns: string | string[];
|
|
34
|
-
eslintrc?: string |
|
|
33
|
+
eslintrc?: string | undefined;
|
|
35
34
|
}>, z.ZodArray<z.ZodEffects<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
|
|
36
|
-
eslintrc: z.ZodOptional<z.
|
|
35
|
+
eslintrc: z.ZodOptional<z.ZodString>;
|
|
37
36
|
patterns: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
|
|
38
37
|
}, "strip", z.ZodTypeAny, {
|
|
39
38
|
patterns: string | string[];
|
|
40
|
-
eslintrc?: string |
|
|
39
|
+
eslintrc?: string | undefined;
|
|
41
40
|
}, {
|
|
42
41
|
patterns: string | string[];
|
|
43
|
-
eslintrc?: string |
|
|
42
|
+
eslintrc?: string | undefined;
|
|
44
43
|
}>]>, {
|
|
45
44
|
patterns: string | string[];
|
|
46
|
-
eslintrc?: string |
|
|
45
|
+
eslintrc?: string | undefined;
|
|
47
46
|
}, string | string[] | {
|
|
48
47
|
patterns: string | string[];
|
|
49
|
-
eslintrc?: string |
|
|
48
|
+
eslintrc?: string | undefined;
|
|
50
49
|
}>, "many">]>, {
|
|
51
50
|
patterns: string | string[];
|
|
52
|
-
eslintrc?: string |
|
|
51
|
+
eslintrc?: string | undefined;
|
|
53
52
|
}[], string | string[] | {
|
|
54
53
|
patterns: string | string[];
|
|
55
|
-
eslintrc?: string |
|
|
54
|
+
eslintrc?: string | undefined;
|
|
56
55
|
} | (string | string[] | {
|
|
57
56
|
patterns: string | string[];
|
|
58
|
-
eslintrc?: string |
|
|
57
|
+
eslintrc?: string | undefined;
|
|
59
58
|
})[]>;
|
|
60
59
|
export type ESLintPluginConfig = z.input<typeof eslintPluginConfigSchema>;
|
|
61
60
|
export type ESLintPluginRunnerConfig = {
|
package/src/lib/meta/groups.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Group } from '@code-pushup/models';
|
|
2
|
-
import { type RuleData } from './
|
|
2
|
+
import { type RuleData } from './parse';
|
|
3
3
|
export declare function groupsFromRuleTypes(rules: RuleData[]): Group[];
|
|
4
4
|
export declare function groupsFromRuleCategories(rules: RuleData[]): Group[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Linter, Rule } from 'eslint';
|
|
2
|
+
export type RuleData = {
|
|
3
|
+
ruleId: string;
|
|
4
|
+
meta: Rule.RuleMetaData;
|
|
5
|
+
options: unknown[] | undefined;
|
|
6
|
+
};
|
|
7
|
+
export declare function parseRuleId(ruleId: string): {
|
|
8
|
+
plugin?: string;
|
|
9
|
+
name: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function isRuleOff(entry: Linter.RuleEntry<unknown[]>): boolean;
|
|
12
|
+
export declare function optionsFromRuleEntry(entry: Linter.RuleEntry<unknown[]>): unknown[];
|
package/src/lib/meta/rules.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
import type { Rule } from 'eslint';
|
|
2
1
|
import type { ESLintTarget } from '../config';
|
|
3
|
-
|
|
4
|
-
ruleId: string;
|
|
5
|
-
meta: Rule.RuleMetaData;
|
|
6
|
-
options: unknown[] | undefined;
|
|
7
|
-
};
|
|
2
|
+
import type { RuleData } from './parse';
|
|
8
3
|
export declare function listRules(targets: ESLintTarget[]): Promise<RuleData[]>;
|
|
9
|
-
export declare function parseRuleId(ruleId: string): {
|
|
10
|
-
plugin?: string;
|
|
11
|
-
name: string;
|
|
12
|
-
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ConfigFormat = 'flat' | 'legacy';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ESLintTarget } from '../../config';
|
|
2
|
+
import type { RuleData } from '../parse';
|
|
3
|
+
import type { ConfigFormat } from './formats';
|
|
4
|
+
export { detectConfigVersion } from './detect';
|
|
5
|
+
export type { ConfigFormat } from './formats';
|
|
6
|
+
export declare function selectRulesLoader(version: ConfigFormat): (target: ESLintTarget) => Promise<RuleData[]>;
|
|
@@ -2,8 +2,11 @@ import type { ESLintTarget } from '../config';
|
|
|
2
2
|
/**
|
|
3
3
|
* Finds all Nx projects in workspace and converts their lint configurations to Code PushUp ESLint plugin parameters.
|
|
4
4
|
*
|
|
5
|
+
* Allows excluding certain projects from the configuration using the `options.exclude` parameter.
|
|
6
|
+
*
|
|
5
7
|
* Use when you wish to automatically include every Nx project in a single Code PushUp project.
|
|
6
|
-
* If you prefer to only
|
|
8
|
+
* If you prefer to include only a subset of your Nx monorepo, specify projects to exclude using the `exclude` option
|
|
9
|
+
* or consider using {@link eslintConfigFromNxProjectAndDeps} for finer control.
|
|
7
10
|
*
|
|
8
11
|
* @example
|
|
9
12
|
* import eslintPlugin, {
|
|
@@ -13,14 +16,18 @@ import type { ESLintTarget } from '../config';
|
|
|
13
16
|
* export default {
|
|
14
17
|
* plugins: [
|
|
15
18
|
* await eslintPlugin(
|
|
16
|
-
* await eslintConfigFromAllNxProjects()
|
|
19
|
+
* await eslintConfigFromAllNxProjects({ exclude: ['server'] })
|
|
17
20
|
* )
|
|
18
21
|
* ]
|
|
19
22
|
* }
|
|
20
23
|
*
|
|
24
|
+
* @param options - Configuration options to filter projects
|
|
25
|
+
* @param options.exclude - Array of project names to exclude from the ESLint configuration
|
|
21
26
|
* @returns ESLint config and patterns, intended to be passed to {@link eslintPlugin}
|
|
22
27
|
*/
|
|
23
|
-
export declare function eslintConfigFromAllNxProjects(
|
|
28
|
+
export declare function eslintConfigFromAllNxProjects(options?: {
|
|
29
|
+
exclude?: string[];
|
|
30
|
+
}): Promise<ESLintTarget[]>;
|
|
24
31
|
/**
|
|
25
32
|
* @deprecated
|
|
26
33
|
* Helper is renamed, please use `eslintConfigFromAllNxProjects` function instead.
|
package/src/lib/setup.d.ts
CHANGED