@nx/eslint 18.0.0-canary.20240201-8762c38 → 18.0.0-canary.20240203-7623471
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/generators.json +1 -1
- package/package.json +4 -4
- package/src/executors/lint/lint.impl.js +38 -18
- package/src/executors/lint/utility/eslint-utils.js +5 -1
- package/src/generators/convert-to-flat-config/generator.js +9 -4
- package/src/generators/init/init-migration.js +23 -9
- package/src/generators/init/init.d.ts +2 -0
- package/src/generators/init/init.js +6 -5
- package/src/generators/lint-project/lint-project.d.ts +2 -0
- package/src/generators/lint-project/lint-project.js +18 -7
- package/src/generators/workspace-rule/workspace-rule.js +1 -1
- package/src/generators/workspace-rules-project/workspace-rules-project.d.ts +1 -0
- package/src/generators/workspace-rules-project/workspace-rules-project.js +1 -0
package/generators.json
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
"version": "0.1",
|
4
4
|
"generators": {
|
5
5
|
"init": {
|
6
|
-
"factory": "./src/generators/init/init#
|
6
|
+
"factory": "./src/generators/init/init#initEsLint",
|
7
7
|
"schema": "./src/generators/init/schema.json",
|
8
8
|
"description": "Set up the ESLint plugin.",
|
9
9
|
"hidden": true
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nx/eslint",
|
3
|
-
"version": "18.0.0-canary.
|
3
|
+
"version": "18.0.0-canary.20240203-7623471",
|
4
4
|
"private": false,
|
5
5
|
"description": "The ESLint plugin for Nx contains executors, generators and utilities used for linting JavaScript/TypeScript projects within an Nx workspace.",
|
6
6
|
"repository": {
|
@@ -33,12 +33,12 @@
|
|
33
33
|
"js-yaml": "4.1.0"
|
34
34
|
},
|
35
35
|
"dependencies": {
|
36
|
-
"@nx/devkit": "18.0.0-canary.
|
37
|
-
"@nx/js": "18.0.0-canary.
|
36
|
+
"@nx/devkit": "18.0.0-canary.20240203-7623471",
|
37
|
+
"@nx/js": "18.0.0-canary.20240203-7623471",
|
38
38
|
"eslint": "^8.0.0",
|
39
39
|
"tslib": "^2.3.0",
|
40
40
|
"typescript": "~5.3.2",
|
41
|
-
"@nx/linter": "18.0.0-canary.
|
41
|
+
"@nx/linter": "18.0.0-canary.20240203-7623471"
|
42
42
|
},
|
43
43
|
"peerDependenciesMeta": {
|
44
44
|
"js-yaml": {
|
@@ -118,14 +118,6 @@ Please see https://nx.dev/guides/eslint for full guidance on how to resolve this
|
|
118
118
|
lintResults = ESLint.getErrorResults(lintResults);
|
119
119
|
}
|
120
120
|
const formatter = await eslint.loadFormatter(normalizedOptions.format);
|
121
|
-
let totalErrors = 0;
|
122
|
-
let totalWarnings = 0;
|
123
|
-
for (const result of lintResults) {
|
124
|
-
if (result.errorCount || result.warningCount) {
|
125
|
-
totalErrors += result.errorCount;
|
126
|
-
totalWarnings += result.warningCount;
|
127
|
-
}
|
128
|
-
}
|
129
121
|
const formattedResults = await formatter.format(lintResults);
|
130
122
|
if (normalizedOptions.outputFile) {
|
131
123
|
const pathToOutputFile = (0, devkit_1.joinPathFragments)(context.root, normalizedOptions.outputFile);
|
@@ -135,20 +127,48 @@ Please see https://nx.dev/guides/eslint for full guidance on how to resolve this
|
|
135
127
|
else {
|
136
128
|
console.info(formattedResults);
|
137
129
|
}
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
if (totalErrors > 0 && printInfo) {
|
142
|
-
console.error('Lint errors found in the listed files.\n');
|
143
|
-
}
|
144
|
-
if (totalWarnings === 0 && totalErrors === 0 && printInfo) {
|
145
|
-
console.info('All files pass linting.\n');
|
130
|
+
const totals = getTotals(lintResults);
|
131
|
+
if (printInfo) {
|
132
|
+
outputPrintInfo(totals);
|
146
133
|
}
|
147
134
|
return {
|
148
135
|
success: normalizedOptions.force ||
|
149
|
-
(
|
136
|
+
(totals.errors === 0 &&
|
150
137
|
(normalizedOptions.maxWarnings === -1 ||
|
151
|
-
|
138
|
+
totals.warnings <= normalizedOptions.maxWarnings)),
|
152
139
|
};
|
153
140
|
}
|
154
141
|
exports.default = run;
|
142
|
+
function getTotals(lintResults) {
|
143
|
+
let errors = 0;
|
144
|
+
let warnings = 0;
|
145
|
+
let fixableErrors = 0;
|
146
|
+
let fixableWarnings = 0;
|
147
|
+
for (const result of lintResults) {
|
148
|
+
errors += result.errorCount || 0;
|
149
|
+
warnings += result.warningCount || 0;
|
150
|
+
fixableErrors += result.fixableErrorCount || 0;
|
151
|
+
fixableWarnings += result.fixableWarningCount || 0;
|
152
|
+
}
|
153
|
+
return {
|
154
|
+
errors,
|
155
|
+
warnings,
|
156
|
+
fixableErrors,
|
157
|
+
fixableWarnings,
|
158
|
+
};
|
159
|
+
}
|
160
|
+
function pluralizedOutput(word, count) {
|
161
|
+
return `${count} ${word}${count === 1 ? '' : 's'}`;
|
162
|
+
}
|
163
|
+
function outputPrintInfo({ errors, warnings, fixableErrors, fixableWarnings, }) {
|
164
|
+
const total = warnings + errors;
|
165
|
+
const totalFixable = fixableErrors + fixableWarnings;
|
166
|
+
if (total <= 0) {
|
167
|
+
console.info('\u2714 All files pass linting\n');
|
168
|
+
return;
|
169
|
+
}
|
170
|
+
console.info(`\u2716 ${pluralizedOutput('problem', total)} (${pluralizedOutput('error', errors)}, ${pluralizedOutput('warning', warnings)})\n`);
|
171
|
+
if (totalFixable <= 0)
|
172
|
+
return;
|
173
|
+
console.info(` ${pluralizedOutput('error', fixableErrors)} and ${pluralizedOutput('warning', fixableWarnings)} are potentially fixable with the \`--fix\` option.\n`);
|
174
|
+
}
|
@@ -38,7 +38,6 @@ async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatCon
|
|
38
38
|
* not be any html files in the project, so keeping it true would break linting every time
|
39
39
|
*/
|
40
40
|
errorOnUnmatchedPattern: false,
|
41
|
-
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives || undefined,
|
42
41
|
};
|
43
42
|
if (useFlatConfig) {
|
44
43
|
if (typeof options.useEslintrc !== 'undefined') {
|
@@ -50,6 +49,9 @@ async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatCon
|
|
50
49
|
if (options.ignorePath !== undefined) {
|
51
50
|
throw new Error('For Flat Config, ESLint removed `ignorePath` and so it is not supported as an option. See https://eslint.org/docs/latest/use/configure/configuration-files-new');
|
52
51
|
}
|
52
|
+
if (options.reportUnusedDisableDirectives) {
|
53
|
+
throw new Error('For Flat Config, ESLint removed `reportedUnusedDisableDirectives` and so it is not supported as an option. See https://eslint.org/docs/latest/use/configure/configuration-files-new');
|
54
|
+
}
|
53
55
|
}
|
54
56
|
else {
|
55
57
|
eslintOptions.rulePaths = options.rulesdir || [];
|
@@ -61,6 +63,8 @@ async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatCon
|
|
61
63
|
* merge the provided config with others it finds automatically.
|
62
64
|
*/
|
63
65
|
eslintOptions.useEslintrc = !options.noEslintrc;
|
66
|
+
eslintOptions.reportUnusedDisableDirectives =
|
67
|
+
options.reportUnusedDisableDirectives || undefined;
|
64
68
|
}
|
65
69
|
const eslint = new ESLint(eslintOptions);
|
66
70
|
return {
|
@@ -46,7 +46,8 @@ function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslint
|
|
46
46
|
const eslintFile = (0, eslint_file_1.findEslintFile)(tree, projectConfig.root);
|
47
47
|
if (eslintFile && !eslintFile.endsWith('.js')) {
|
48
48
|
if (projectConfig.targets) {
|
49
|
-
const eslintTargets = Object.keys(projectConfig.targets || {}).filter((t) => projectConfig.targets[t].executor === '@nx/eslint:lint'
|
49
|
+
const eslintTargets = Object.keys(projectConfig.targets || {}).filter((t) => projectConfig.targets[t].executor === '@nx/eslint:lint' ||
|
50
|
+
projectConfig.targets[t].command?.includes('eslint'));
|
50
51
|
let ignorePath;
|
51
52
|
for (const target of eslintTargets) {
|
52
53
|
// remove any obsolete `eslintConfig` options pointing to the old config file
|
@@ -59,10 +60,14 @@ function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslint
|
|
59
60
|
}
|
60
61
|
(0, devkit_1.updateProjectConfiguration)(tree, project, projectConfig);
|
61
62
|
}
|
62
|
-
const
|
63
|
-
nxJson.targetDefaults[t].executor === '@nx/eslint:lint'
|
63
|
+
const nxHasEsLintTargets = Object.keys(nxJson.targetDefaults || {}).some((t) => (t === '@nx/eslint:lint' ||
|
64
|
+
nxJson.targetDefaults[t].executor === '@nx/eslint:lint' ||
|
65
|
+
nxJson.targetDefaults[t].command?.includes('eslint')) &&
|
64
66
|
projectConfig.targets?.[t]);
|
65
|
-
|
67
|
+
const nxHasEsLintPlugin = (nxJson.plugins || []).some((p) => typeof p === 'string'
|
68
|
+
? p === '@nx/eslint/plugin'
|
69
|
+
: p.plugin === '@nx/eslint/plugin');
|
70
|
+
if (nxHasEsLintTargets || nxHasEsLintPlugin || eslintTargets.length > 0) {
|
66
71
|
convertConfigToFlatConfig(tree, projectConfig.root, eslintFile, 'eslint.config.js', ignorePath);
|
67
72
|
eslintIgnoreFiles.add(`${projectConfig.root}/.eslintignore`);
|
68
73
|
if (ignorePath) {
|
@@ -8,6 +8,8 @@ const global_eslint_config_1 = require("./global-eslint-config");
|
|
8
8
|
const flat_config_1 = require("../../utils/flat-config");
|
9
9
|
const versions_1 = require("../../utils/versions");
|
10
10
|
const ast_utils_1 = require("../utils/flat-config/ast-utils");
|
11
|
+
const plugin_1 = require("../utils/plugin");
|
12
|
+
const config_file_1 = require("../../utils/config-file");
|
11
13
|
function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, keepExistingVersions) {
|
12
14
|
const rootEslintConfig = (0, eslint_file_1.findEslintFile)(tree);
|
13
15
|
let skipCleanup = false;
|
@@ -35,20 +37,32 @@ function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, keepExisti
|
|
35
37
|
}
|
36
38
|
// update extends in all projects' eslint configs
|
37
39
|
projects.forEach((project) => {
|
40
|
+
let eslintFile;
|
38
41
|
const lintTarget = findLintTarget(project);
|
39
42
|
if (lintTarget) {
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
// If target is configured in project.json, read file from target options.
|
44
|
+
eslintFile =
|
45
|
+
lintTarget.options?.eslintConfig || (0, eslint_file_1.findEslintFile)(tree, project.root);
|
46
|
+
}
|
47
|
+
else if ((0, plugin_1.hasEslintPlugin)(tree)) {
|
48
|
+
// Otherwise, if `@nx/eslint/plugin` is used, match any of the known config files.
|
49
|
+
for (const f of config_file_1.ESLINT_CONFIG_FILENAMES) {
|
50
|
+
if (tree.exists((0, devkit_1.joinPathFragments)(project.root, f))) {
|
51
|
+
eslintFile = f;
|
52
|
+
break;
|
49
53
|
}
|
50
54
|
}
|
51
55
|
}
|
56
|
+
if (eslintFile) {
|
57
|
+
const projectEslintPath = (0, devkit_1.joinPathFragments)(project.root, eslintFile);
|
58
|
+
if (skipCleanup) {
|
59
|
+
const content = tree.read(projectEslintPath, 'utf-8');
|
60
|
+
tree.write(projectEslintPath, content.replace(rootEslintConfig, rootEslintConfig.replace('.base.', '.')));
|
61
|
+
}
|
62
|
+
else {
|
63
|
+
migrateEslintFile(projectEslintPath, tree);
|
64
|
+
}
|
65
|
+
}
|
52
66
|
});
|
53
67
|
}
|
54
68
|
exports.migrateConfigToMonorepoStyle = migrateConfigToMonorepoStyle;
|
@@ -3,5 +3,7 @@ export interface LinterInitOptions {
|
|
3
3
|
skipPackageJson?: boolean;
|
4
4
|
keepExistingVersions?: boolean;
|
5
5
|
updatePackageScripts?: boolean;
|
6
|
+
addPlugin?: boolean;
|
6
7
|
}
|
8
|
+
export declare function initEsLint(tree: Tree, options: LinterInitOptions): Promise<GeneratorCallback>;
|
7
9
|
export declare function lintInitGenerator(tree: Tree, options: LinterInitOptions): Promise<GeneratorCallback>;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.lintInitGenerator = void 0;
|
3
|
+
exports.lintInitGenerator = exports.initEsLint = void 0;
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
5
5
|
const update_package_scripts_1 = require("@nx/devkit/src/utils/update-package-scripts");
|
6
6
|
const versions_1 = require("../../utils/versions");
|
@@ -50,10 +50,10 @@ function addPlugin(tree) {
|
|
50
50
|
(0, devkit_1.updateNxJson)(tree, nxJson);
|
51
51
|
}
|
52
52
|
async function initEsLint(tree, options) {
|
53
|
-
|
53
|
+
options.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false';
|
54
54
|
const hasPlugin = (0, plugin_2.hasEslintPlugin)(tree);
|
55
55
|
const rootEslintFile = (0, eslint_file_1.findEslintFile)(tree);
|
56
|
-
if (rootEslintFile &&
|
56
|
+
if (rootEslintFile && options.addPlugin && !hasPlugin) {
|
57
57
|
addPlugin(tree);
|
58
58
|
if (options.updatePackageScripts) {
|
59
59
|
await (0, update_package_scripts_1.updatePackageScripts)(tree, plugin_1.createNodes);
|
@@ -64,7 +64,7 @@ async function initEsLint(tree, options) {
|
|
64
64
|
return () => { };
|
65
65
|
}
|
66
66
|
updateProductionFileset(tree);
|
67
|
-
if (
|
67
|
+
if (options.addPlugin) {
|
68
68
|
addPlugin(tree);
|
69
69
|
}
|
70
70
|
else {
|
@@ -83,7 +83,8 @@ async function initEsLint(tree, options) {
|
|
83
83
|
}
|
84
84
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
85
85
|
}
|
86
|
+
exports.initEsLint = initEsLint;
|
86
87
|
async function lintInitGenerator(tree, options) {
|
87
|
-
return await initEsLint(tree, options);
|
88
|
+
return await initEsLint(tree, { addPlugin: false, ...options });
|
88
89
|
}
|
89
90
|
exports.lintInitGenerator = lintInitGenerator;
|
@@ -11,6 +11,8 @@ interface LintProjectOptions {
|
|
11
11
|
unitTestRunner?: string;
|
12
12
|
rootProject?: boolean;
|
13
13
|
keepExistingVersions?: boolean;
|
14
|
+
addPlugin?: boolean;
|
14
15
|
}
|
15
16
|
export declare function lintProjectGenerator(tree: Tree, options: LintProjectOptions): Promise<GeneratorCallback>;
|
17
|
+
export declare function lintProjectGeneratorInternal(tree: Tree, options: LintProjectOptions): Promise<GeneratorCallback>;
|
16
18
|
export {};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.lintProjectGenerator = void 0;
|
3
|
+
exports.lintProjectGeneratorInternal = exports.lintProjectGenerator = void 0;
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
5
5
|
const eslint_file_1 = require("../utils/eslint-file");
|
6
6
|
const path_1 = require("path");
|
@@ -12,10 +12,16 @@ const ast_utils_1 = require("../utils/flat-config/ast-utils");
|
|
12
12
|
const config_file_1 = require("../../utils/config-file");
|
13
13
|
const plugin_1 = require("../utils/plugin");
|
14
14
|
const setup_root_eslint_1 = require("./setup-root-eslint");
|
15
|
-
|
15
|
+
function lintProjectGenerator(tree, options) {
|
16
|
+
return lintProjectGeneratorInternal(tree, { addPlugin: false, ...options });
|
17
|
+
}
|
18
|
+
exports.lintProjectGenerator = lintProjectGenerator;
|
19
|
+
async function lintProjectGeneratorInternal(tree, options) {
|
20
|
+
options.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false';
|
16
21
|
const tasks = [];
|
17
22
|
const initTask = await (0, init_1.lintInitGenerator)(tree, {
|
18
23
|
skipPackageJson: options.skipPackageJson,
|
24
|
+
addPlugin: options.addPlugin,
|
19
25
|
});
|
20
26
|
tasks.push(initTask);
|
21
27
|
const rootEsLintTask = (0, setup_root_eslint_1.setupRootEsLint)(tree, {
|
@@ -97,7 +103,7 @@ async function lintProjectGenerator(tree, options) {
|
|
97
103
|
}
|
98
104
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
99
105
|
}
|
100
|
-
exports.
|
106
|
+
exports.lintProjectGeneratorInternal = lintProjectGeneratorInternal;
|
101
107
|
function createEsLintConfiguration(tree, projectConfig, setParserOptionsProject, rootProject) {
|
102
108
|
// we are only extending root for non-standalone projects or their complementary e2e apps
|
103
109
|
const extendedRootConfig = rootProject ? undefined : (0, eslint_file_1.findEslintFile)(tree);
|
@@ -204,10 +210,15 @@ function isMigrationToMonorepoNeeded(projects, tree) {
|
|
204
210
|
if (!rootProject || !rootProject.targets) {
|
205
211
|
return false;
|
206
212
|
}
|
213
|
+
// check if we're inferring lint target from `@nx/eslint/plugin`
|
214
|
+
if ((0, plugin_1.hasEslintPlugin)(tree)) {
|
215
|
+
for (const f of config_file_1.ESLINT_CONFIG_FILENAMES) {
|
216
|
+
if (tree.exists(f)) {
|
217
|
+
return true;
|
218
|
+
}
|
219
|
+
}
|
220
|
+
}
|
207
221
|
// find if root project has lint target
|
208
222
|
const lintTarget = (0, init_migration_1.findLintTarget)(rootProject);
|
209
|
-
|
210
|
-
return false;
|
211
|
-
}
|
212
|
-
return true;
|
223
|
+
return !!lintTarget;
|
213
224
|
}
|
@@ -9,7 +9,7 @@ const workspace_lint_rules_1 = require("../../utils/workspace-lint-rules");
|
|
9
9
|
const workspace_rules_project_1 = require("../workspace-rules-project/workspace-rules-project");
|
10
10
|
async function lintWorkspaceRuleGenerator(tree, options) {
|
11
11
|
// Ensure that the workspace rules project has been created
|
12
|
-
const projectGeneratorCallback = await (0, workspace_rules_project_1.lintWorkspaceRulesProjectGenerator)(tree, { skipFormat: true });
|
12
|
+
const projectGeneratorCallback = await (0, workspace_rules_project_1.lintWorkspaceRulesProjectGenerator)(tree, { skipFormat: true, addPlugin: process.env.NX_ADD_PLUGINS !== 'false' });
|
13
13
|
const ruleDir = (0, devkit_1.joinPathFragments)(workspace_lint_rules_1.workspaceLintPluginDir, options.directory ?? '');
|
14
14
|
// Generate the required files for the new rule
|
15
15
|
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), ruleDir, {
|
@@ -3,5 +3,6 @@ export declare const WORKSPACE_RULES_PROJECT_NAME = "eslint-rules";
|
|
3
3
|
export declare const WORKSPACE_PLUGIN_DIR = "tools/eslint-rules";
|
4
4
|
export interface LintWorkspaceRulesProjectGeneratorOptions {
|
5
5
|
skipFormat?: boolean;
|
6
|
+
addPlugin?: boolean;
|
6
7
|
}
|
7
8
|
export declare function lintWorkspaceRulesProjectGenerator(tree: Tree, options?: LintWorkspaceRulesProjectGeneratorOptions): Promise<GeneratorCallback>;
|
@@ -41,6 +41,7 @@ async function lintWorkspaceRulesProjectGenerator(tree, options = {}) {
|
|
41
41
|
}
|
42
42
|
// Add jest to the project and return installation task
|
43
43
|
tasks.push(await configurationGenerator(tree, {
|
44
|
+
...options,
|
44
45
|
project: exports.WORKSPACE_RULES_PROJECT_NAME,
|
45
46
|
supportTsx: false,
|
46
47
|
skipSerializers: true,
|