@nx/eslint 24.0.0-beta.2 → 24.0.0-beta.4

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.
Files changed (29) hide show
  1. package/dist/internal.d.ts +0 -1
  2. package/dist/src/generators/init/init-migration.d.ts +1 -2
  3. package/dist/src/generators/init/init-migration.js +2 -13
  4. package/dist/src/generators/init/init.d.ts +0 -1
  5. package/dist/src/generators/init/init.js +5 -42
  6. package/dist/src/generators/lint-project/lint-project.d.ts +0 -2
  7. package/dist/src/generators/lint-project/lint-project.js +10 -33
  8. package/dist/src/generators/workspace-rule/workspace-rule.js +0 -3
  9. package/dist/src/generators/workspace-rules-project/workspace-rules-project.d.ts +0 -1
  10. package/dist/src/migrations/update-23-1-0/convert-to-flat-config.md +9 -9
  11. package/dist/src/migrations/update-24-0-0/finish-inferred-conversion.md +12 -0
  12. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.d.ts +6 -0
  13. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.js +10 -0
  14. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.md +38 -0
  15. package/dist/src/utils/config-file.d.ts +0 -2
  16. package/dist/src/utils/config-file.js +0 -44
  17. package/executors.json +1 -7
  18. package/migrations.json +7 -0
  19. package/package.json +6 -6
  20. package/dist/src/executors/lint/lint.impl.d.ts +0 -5
  21. package/dist/src/executors/lint/lint.impl.js +0 -190
  22. package/dist/src/executors/lint/schema.d.ts +0 -32
  23. package/dist/src/executors/lint/schema.json +0 -154
  24. package/dist/src/executors/lint/utility/eslint-utils.d.ts +0 -6
  25. package/dist/src/executors/lint/utility/eslint-utils.js +0 -106
  26. package/dist/src/generators/utils/eslint-targets.d.ts +0 -2
  27. package/dist/src/generators/utils/eslint-targets.js +0 -17
  28. package/dist/src/utils/deprecation.d.ts +0 -3
  29. package/dist/src/utils/deprecation.js +0 -15
@@ -4,4 +4,3 @@ export { useFlatConfig } from './src/utils/flat-config';
4
4
  export { javaScriptOverride, typeScriptOverride, } from './src/generators/init/global-eslint-config';
5
5
  export { setupRootEsLint } from './src/generators/lint-project/setup-root-eslint';
6
6
  export { getInstalledEslintVersion, typescriptESLintVersion, versions, } from './src/utils/versions';
7
- export type { Schema } from './src/executors/lint/schema';
@@ -1,3 +1,2 @@
1
- import { GeneratorCallback, ProjectConfiguration, TargetConfiguration, Tree } from '@nx/devkit';
1
+ import { GeneratorCallback, ProjectConfiguration, Tree } from '@nx/devkit';
2
2
  export declare function migrateConfigToMonorepoStyle(projects: ProjectConfiguration[], tree: Tree, unitTestRunner: string, eslintConfigFormat: 'mjs' | 'cjs', keepExistingVersions?: boolean): GeneratorCallback;
3
- export declare function findLintTarget(project: ProjectConfiguration): TargetConfiguration;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.migrateConfigToMonorepoStyle = migrateConfigToMonorepoStyle;
4
- exports.findLintTarget = findLintTarget;
5
4
  const devkit_1 = require("@nx/devkit");
6
5
  const path_1 = require("path");
7
6
  const eslint_file_1 = require("../utils/eslint-file");
@@ -50,14 +49,8 @@ function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, eslintConf
50
49
  // update extends in all projects' eslint configs
51
50
  projects.forEach((project) => {
52
51
  let eslintFile;
53
- const lintTarget = findLintTarget(project);
54
- if (lintTarget) {
55
- // If target is configured in project.json, read file from target options.
56
- eslintFile =
57
- lintTarget.options?.eslintConfig || (0, eslint_file_1.findEslintFile)(tree, project.root);
58
- }
59
- else if ((0, plugin_1.hasEslintPlugin)(tree)) {
60
- // Otherwise, if `@nx/eslint/plugin` is used, match any of the known config files.
52
+ if ((0, plugin_1.hasEslintPlugin)(tree)) {
53
+ // If `@nx/eslint/plugin` is used, match any of the known config files.
61
54
  for (const f of config_file_1.ESLINT_CONFIG_FILENAMES) {
62
55
  if (tree.exists((0, devkit_1.joinPathFragments)(project.root, f))) {
63
56
  eslintFile = f;
@@ -80,10 +73,6 @@ function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, eslintConf
80
73
  '@nx/eslint-plugin': versions_1.nxVersion,
81
74
  }, undefined, keepExistingVersions ?? true);
82
75
  }
83
- function findLintTarget(project) {
84
- return Object.values(project.targets ?? {}).find((target) => target.executor === '@nx/eslint:lint' ||
85
- target.executor === '@nx/linter:eslint');
86
- }
87
76
  function migrateEslintFile(projectEslintPath, tree) {
88
77
  const baseFile = (0, eslint_file_1.findEslintFile)(tree);
89
78
  if ((0, eslint_file_1.isEslintConfigSupported)(tree)) {
@@ -3,7 +3,6 @@ export interface LinterInitOptions {
3
3
  skipPackageJson?: boolean;
4
4
  keepExistingVersions?: boolean;
5
5
  updatePackageScripts?: boolean;
6
- addPlugin?: boolean;
7
6
  eslintConfigFormat?: 'mjs' | 'cjs';
8
7
  }
9
8
  export declare function initEsLint(tree: Tree, options: LinterInitOptions): Promise<GeneratorCallback>;
@@ -21,34 +21,6 @@ function updateProductionFileset(tree, format = 'mjs') {
21
21
  }
22
22
  (0, devkit_1.updateNxJson)(tree, nxJson);
23
23
  }
24
- function addTargetDefaults(tree, format) {
25
- const nxJson = (0, devkit_1.readNxJson)(tree) ?? {};
26
- // `@nx/eslint:lint` is an executor identifier — match defaults keyed on
27
- // the executor, not on a target named that string.
28
- const existing = (0, internal_1.findTargetDefault)(nxJson.targetDefaults, {
29
- executor: '@nx/eslint:lint',
30
- });
31
- const patch = {};
32
- if (existing?.cache === undefined)
33
- patch.cache = true;
34
- if (existing?.inputs === undefined) {
35
- patch.inputs = [
36
- 'default',
37
- '^default',
38
- `{workspaceRoot}/.eslintrc.json`,
39
- `{workspaceRoot}/.eslintignore`,
40
- `{workspaceRoot}/eslint.config.${format}`,
41
- '{workspaceRoot}/tools/eslint-rules/**/*',
42
- ];
43
- }
44
- if (Object.keys(patch).length > 0) {
45
- (0, internal_1.upsertTargetDefault)(tree, nxJson, {
46
- executor: '@nx/eslint:lint',
47
- ...patch,
48
- });
49
- (0, devkit_1.updateNxJson)(tree, nxJson);
50
- }
51
- }
52
24
  function updateVsCodeRecommendedExtensions(host) {
53
25
  if (!host.exists('.vscode/extensions.json')) {
54
26
  return;
@@ -64,10 +36,6 @@ function updateVsCodeRecommendedExtensions(host) {
64
36
  }
65
37
  async function initEsLint(tree, options) {
66
38
  (0, assert_supported_eslint_version_1.assertSupportedEslintVersion)(tree);
67
- const nxJson = (0, devkit_1.readNxJson)(tree);
68
- const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
69
- nxJson.useInferencePlugins !== false;
70
- options.addPlugin ??= addPluginDefault;
71
39
  options.eslintConfigFormat ??= 'mjs';
72
40
  const hasPlugin = (0, plugin_2.hasEslintPlugin)(tree);
73
41
  const rootEslintFile = (0, eslint_file_1.findEslintFile)(tree);
@@ -89,7 +57,7 @@ async function initEsLint(tree, options) {
89
57
  '_eslint:lint',
90
58
  '_eslint-lint',
91
59
  ];
92
- if (rootEslintFile && options.addPlugin && !hasPlugin) {
60
+ if (rootEslintFile && !hasPlugin) {
93
61
  await (0, internal_1.addPlugin)(tree, graph, '@nx/eslint/plugin', plugin_1.createNodes, {
94
62
  targetName: lintTargetNames,
95
63
  }, options.updatePackageScripts);
@@ -100,14 +68,9 @@ async function initEsLint(tree, options) {
100
68
  }
101
69
  updateProductionFileset(tree, options.eslintConfigFormat);
102
70
  updateVsCodeRecommendedExtensions(tree);
103
- if (options.addPlugin) {
104
- await (0, internal_1.addPlugin)(tree, graph, '@nx/eslint/plugin', plugin_1.createNodes, {
105
- targetName: lintTargetNames,
106
- }, options.updatePackageScripts);
107
- }
108
- else {
109
- addTargetDefaults(tree, options.eslintConfigFormat);
110
- }
71
+ await (0, internal_1.addPlugin)(tree, graph, '@nx/eslint/plugin', plugin_1.createNodes, {
72
+ targetName: lintTargetNames,
73
+ }, options.updatePackageScripts);
111
74
  const tasks = [];
112
75
  if (!options.skipPackageJson) {
113
76
  const { eslintVersion } = (0, versions_1.versions)(tree);
@@ -120,5 +83,5 @@ async function initEsLint(tree, options) {
120
83
  return (0, devkit_1.runTasksInSerial)(...tasks);
121
84
  }
122
85
  async function lintInitGenerator(tree, options) {
123
- return await initEsLint(tree, { addPlugin: false, ...options });
86
+ return await initEsLint(tree, options);
124
87
  }
@@ -15,12 +15,10 @@ interface LintProjectOptions {
15
15
  unitTestRunner?: string;
16
16
  rootProject?: boolean;
17
17
  keepExistingVersions?: boolean;
18
- addPlugin?: boolean;
19
18
  eslintConfigFormat?: 'mjs' | 'cjs';
20
19
  /**
21
20
  * @internal
22
21
  */
23
- addExplicitTargets?: boolean;
24
22
  addPackageJsonDependencyChecks?: boolean;
25
23
  }
26
24
  export declare function lintProjectGenerator(tree: Tree, options: LintProjectOptions): Promise<GeneratorCallback>;
@@ -6,7 +6,6 @@ const devkit_1 = require("@nx/devkit");
6
6
  const eslint_file_1 = require("../utils/eslint-file");
7
7
  const path_1 = require("path");
8
8
  const init_1 = require("../init/init");
9
- const deprecation_1 = require("../../utils/deprecation");
10
9
  const init_migration_1 = require("../init/init-migration");
11
10
  const flat_config_1 = require("../../utils/flat-config");
12
11
  const ast_utils_1 = require("../utils/flat-config/ast-utils");
@@ -16,18 +15,13 @@ const versions_1 = require("../../utils/versions");
16
15
  const setup_root_eslint_1 = require("./setup-root-eslint");
17
16
  const internal_1 = require("@nx/js/internal");
18
17
  function lintProjectGenerator(tree, options) {
19
- return lintProjectGeneratorInternal(tree, { addPlugin: false, ...options });
18
+ return lintProjectGeneratorInternal(tree, options);
20
19
  }
21
20
  async function lintProjectGeneratorInternal(tree, options) {
22
- const nxJson = (0, devkit_1.readNxJson)(tree);
23
21
  options.eslintConfigFormat ??= 'mjs';
24
- const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
25
- nxJson.useInferencePlugins !== false;
26
- options.addPlugin ??= addPluginDefault;
27
22
  const tasks = [];
28
23
  const initTask = await (0, init_1.lintInitGenerator)(tree, {
29
24
  skipPackageJson: options.skipPackageJson,
30
- addPlugin: options.addPlugin,
31
25
  eslintConfigFormat: options.eslintConfigFormat,
32
26
  });
33
27
  tasks.push(initTask);
@@ -49,31 +43,15 @@ async function lintProjectGeneratorInternal(tree, options) {
49
43
  isBuildableLibraryProject(tree, projectConfig)) {
50
44
  lintFilePatterns.push(`{projectRoot}/package.json`);
51
45
  }
52
- const hasPlugin = (0, plugin_1.hasEslintPlugin)(tree);
53
- if (hasPlugin && !options.addExplicitTargets) {
54
- if (lintFilePatterns &&
55
- lintFilePatterns.length &&
56
- lintFilePatterns.some((p) => !['./src', '{projectRoot}', projectConfig.root].includes(p))) {
57
- projectConfig.targets ??= {};
58
- projectConfig.targets['lint'] = {
59
- command: `eslint ${lintFilePatterns
60
- .join(' ')
61
- .replace('{projectRoot}', projectConfig.root)}`,
62
- };
63
- }
64
- }
65
- else {
66
- (0, deprecation_1.warnEslintExecutorGenerating)();
46
+ if (lintFilePatterns &&
47
+ lintFilePatterns.length &&
48
+ lintFilePatterns.some((p) => !['./src', '{projectRoot}', projectConfig.root].includes(p))) {
67
49
  projectConfig.targets ??= {};
68
50
  projectConfig.targets['lint'] = {
69
- executor: '@nx/eslint:lint',
51
+ command: `eslint ${lintFilePatterns
52
+ .join(' ')
53
+ .replace('{projectRoot}', projectConfig.root)}`,
70
54
  };
71
- if (lintFilePatterns && lintFilePatterns.length) {
72
- // only add lintFilePatterns if they are explicitly defined
73
- projectConfig.targets['lint'].options = {
74
- lintFilePatterns,
75
- };
76
- }
77
55
  }
78
56
  // we are adding new project which is not the root project or
79
57
  // companion e2e app so we should check if migration to
@@ -274,10 +252,9 @@ function rootHasEslintLintTarget(targets) {
274
252
  return false;
275
253
  }
276
254
  for (const targetConfig of Object.values(targets)) {
277
- if (['@nx/eslint:lint', '@nx/linter:eslint'].includes(targetConfig.executor) ||
278
- (targetConfig.executor === 'nx:run-commands' &&
279
- targetConfig.options?.command &&
280
- targetConfig.options?.command.startsWith('eslint '))) {
255
+ if (targetConfig.executor === 'nx:run-commands' &&
256
+ targetConfig.options?.command &&
257
+ targetConfig.options?.command.startsWith('eslint ')) {
281
258
  return true;
282
259
  }
283
260
  }
@@ -17,12 +17,9 @@ async function lintWorkspaceRuleGenerator(tree, options) {
17
17
  // recommended replacement is the separate `@typescript-eslint/rule-tester`
18
18
  // package, whose flat-style API works for both flat and eslintrc workspaces.
19
19
  const { typescriptESLintVersion } = (0, versions_1.versions)(tree);
20
- const nxJson = (0, devkit_1.readNxJson)(tree);
21
20
  // Ensure that the workspace rules project has been created
22
21
  tasks.push(await (0, workspace_rules_project_1.lintWorkspaceRulesProjectGenerator)(tree, {
23
22
  skipFormat: true,
24
- addPlugin: process.env.NX_ADD_PLUGINS !== 'false' &&
25
- nxJson.useInferencePlugins !== false,
26
23
  }));
27
24
  tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@typescript-eslint/rule-tester': typescriptESLintVersion }, undefined, true));
28
25
  const ruleDir = (0, devkit_1.joinPathFragments)(workspace_lint_rules_1.workspaceLintPluginDir, options.directory ?? '');
@@ -3,6 +3,5 @@ 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;
7
6
  }
8
7
  export declare function lintWorkspaceRulesProjectGenerator(tree: Tree, options?: LintWorkspaceRulesProjectGeneratorOptions): Promise<GeneratorCallback>;
@@ -34,17 +34,17 @@ The pre-pass does NOT:
34
34
  - Decide whether a generated `FlatCompat` shim should become flat-native config.
35
35
  - Make the workspace pass lint after ESLint v9 changed which rules its preset defaults enable.
36
36
 
37
- Everything the pre-pass could not finish is forwarded to you in `<advisory_context>`.
37
+ Everything the pre-pass could not finish is forwarded to you in `impl.agentContext`.
38
38
 
39
- How to read the wrapper sections above this file:
39
+ How to read the `impl` fields of the step's `nx_migrate_prompt` block:
40
40
 
41
- - `<files_changed>` lists files the pre-pass wrote. Verify the new shape is in place; do not re-apply the same edit. It is absent when the pre-pass made no changes (for example a workspace that was already on flat config).
42
- - `<advisory_context>` lists detections the pre-pass forwarded because it could not safely complete them. Every entry is pending work. Address each one in the relevant section below.
41
+ - `impl.changes` lists files the pre-pass wrote. Verify the new shape is in place; do not re-apply the same edit. It is empty when the pre-pass made no changes (for example a workspace that was already on flat config).
42
+ - `impl.agentContext` lists detections the pre-pass forwarded because it could not safely complete them. Every entry is pending work. Address each one in the relevant section below.
43
43
 
44
44
  </pre_pass_summary>
45
45
 
46
46
  <handoff_guidance>
47
- In your handoff `summary` (1 to 3 sentences per the system prompt), name the sections you applied and explicitly call out any you skipped because they did not apply (for example "no JavaScript-based configs and no removed formatters in this workspace").
47
+ In your handoff `summary` (1 to 3 sentences, per the handoff format), name the sections you applied and explicitly call out any you skipped because they did not apply (for example "no JavaScript-based configs and no removed formatters in this workspace").
48
48
  </handoff_guidance>
49
49
 
50
50
  ## Pre-Migration Checklist
@@ -87,7 +87,7 @@ If the workspace already uses `eslint.config.*` at the root and in every project
87
87
 
88
88
  ## 2. Convert JavaScript-based ESLint configs the pre-pass skipped
89
89
 
90
- **Search pattern**: `.eslintrc.js` and `.eslintrc.cjs` files (forwarded in `<advisory_context>`).
90
+ **Search pattern**: `.eslintrc.js` and `.eslintrc.cjs` files (forwarded in `impl.agentContext`).
91
91
 
92
92
  **What changed**: the pre-pass only converts JSON and YAML eslintrc files. JavaScript-based configs run arbitrary code, so they need manual conversion.
93
93
 
@@ -126,7 +126,7 @@ export default [
126
126
 
127
127
  ## 3. Convert FlatCompat shims to flat-native config where low-risk
128
128
 
129
- **Search pattern**: `FlatCompat`, `@eslint/eslintrc`, `compat.extends(`, `compat.config(` in the generated `eslint.config.*` files (listed in `<files_changed>`).
129
+ **Search pattern**: `FlatCompat`, `@eslint/eslintrc`, `compat.extends(`, `compat.config(` in the generated `eslint.config.*` files (listed in `impl.changes`).
130
130
 
131
131
  **What changed**: `FlatCompat` is a runtime shim that adapts eslintrc-style `extends` into flat config. Many plugins now ship native flat presets, which are clearer and avoid the shim.
132
132
 
@@ -169,7 +169,7 @@ This is the core requirement of the migration: the workspace must lint cleanly w
169
169
 
170
170
  ESLint v9 and typescript-eslint v8 changed which rules their recommended sets enable. A rule the user never configured may now report errors. Disable those rules; do not edit source files to satisfy them.
171
171
 
172
- The set of rules the user explicitly configured before the migration is in `<advisory_context>` (the entry that starts with "Passing-state requirement").
172
+ The set of rules the user explicitly configured before the migration is in `impl.agentContext` (the entry that starts with "Passing-state requirement").
173
173
 
174
174
  **Procedure**:
175
175
 
@@ -213,7 +213,7 @@ You cannot make lint pass without either editing source files or disabling a rul
213
213
 
214
214
  ## 5. Fix removed output formatters
215
215
 
216
- **Search pattern**: the `format` option on lint targets (forwarded in `<advisory_context>`).
216
+ **Search pattern**: the `format` option on lint targets (forwarded in `impl.agentContext`).
217
217
 
218
218
  **What changed**: ESLint v9 removed several built-in output formatters. The built-ins that remain are `stylish`, `html`, `json`, and `json-with-metadata`. Removed: `compact`, `codeframe`, `unix`, `visualstudio`, `table`, `checkstyle`, `jslint-xml`, `junit`, `tap`.
219
219
 
@@ -0,0 +1,12 @@
1
+ # Replace removed @nx/eslint executors with inferred tasks
2
+
3
+ Nx 24 removed `@nx/eslint:lint` (including the old `@nrwl/linter:eslint` name).
4
+
5
+ Before changing anything, check for leftover work: a project target, a package.json target or a `targetDefaults` entry still uses a removed executor, or the advisory context reports a conversion error. If none applies, make no changes and stop. Treat each advisory-context item as pending work.
6
+
7
+ 1. Inspect all affected projects and workspace defaults. Repair config-loading errors first. Do not restore executor registrations or install older Nx packages.
8
+ 2. Ensure flat ESLint configs load and preserve file patterns, exclusions, rules and output flags. Do not weaken rules to make validation pass.
9
+ 3. Register `@nx/eslint/plugin` with options/includes that preserve custom target names and mixed inferred/explicit projects. Replace remaining removed-executor targets, including those in package.json and filtered targetDefaults. Transfer their behavior before removing obsolete defaults. Preserve configurations, dependencies, cache inputs/outputs and environment behavior. Do not silently delete unsupported options or unrelated targets. Migrate old @nrwl aliases too.
10
+ 4. Run project graph creation with the daemon and graph cache disabled (`NX_DAEMON=false NX_CACHE_PROJECT_GRAPH=false`), using the workspace package manager. Inspect resolved project targets and verify each migrated entrypoint exists and is inferred (a thin alias to an inferred target is acceptable). Resolve graph errors before completing this migration, even if task validation was skipped. Configs must load for subsequent migrations.
11
+ 5. By default run relevant real builds/tests with task cache disabled, including alternate configurations. Honor an existing preference to skip expensive task validation; otherwise offer that option when validation is slow. Skipping expensive tasks never skips conversion or the graph check. Report each skipped task as unverified. Never weaken assertions or change application behavior to make checks pass.
12
+ 6. Report converted projects, graph validation, task results and any skipped checks. Unconverted targets or a broken graph mean the migration is incomplete. Investigate task failures and distinguish missing environment prerequisites from conversion regressions; do not claim a working workspace with unresolved regressions.
@@ -0,0 +1,6 @@
1
+ import type { Tree } from '@nx/devkit';
2
+ export default function update(tree: Tree): Promise<{
3
+ nextSteps?: string[];
4
+ agentContext?: string[];
5
+ skipAgentic?: boolean;
6
+ }>;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = update;
4
+ const internal_1 = require("@nx/devkit/internal");
5
+ function update(tree) {
6
+ return (0, internal_1.migrateRemovedExecutors)(tree, ['@nx/eslint:lint', '@nrwl/linter:eslint'], async (tree, options) => {
7
+ const { convertToInferred } = require('../../generators/convert-to-inferred/convert-to-inferred');
8
+ return convertToInferred(tree, options);
9
+ });
10
+ }
@@ -0,0 +1,38 @@
1
+ #### Convert `@nx/eslint:lint` targets to inferred tasks
2
+
3
+ Nx 24 removes the `@nx/eslint:lint` executor and its `@nrwl/linter:eslint` alias. The migration registers `@nx/eslint/plugin` in `nx.json` and converts the targets that use those executors to inferred tasks. Options the plugin does not infer stay on the target. A target with nothing left to override is removed from project configuration. When several projects share the same remaining options, those options move to a `targetDefaults` entry scoped to the plugin. `targetDefaults` entries keyed by a removed executor are removed once no target uses that executor.
4
+
5
+ The migration lists the targets the converter cannot convert safely. In agentic runs, an AI prompt finishes them and validates the project graph.
6
+
7
+ #### Sample code changes
8
+
9
+ ##### Before
10
+
11
+ ```json title="myapp/project.json"
12
+ {
13
+ "name": "myapp",
14
+ "targets": {
15
+ "lint": {
16
+ "executor": "@nx/eslint:lint",
17
+ "options": {
18
+ "eslintConfig": "myapp/.eslintrc.json"
19
+ }
20
+ }
21
+ }
22
+ }
23
+ ```
24
+
25
+ ##### After
26
+
27
+ ```json title="nx.json"
28
+ {
29
+ "plugins": [
30
+ {
31
+ "plugin": "@nx/eslint/plugin",
32
+ "options": {
33
+ "targetName": "lint"
34
+ }
35
+ }
36
+ ]
37
+ }
38
+ ```
@@ -6,5 +6,3 @@ export declare const baseEsLintConfigFile = ".eslintrc.base.json";
6
6
  export declare const baseEsLintFlatConfigFile = "eslint.base.config.mjs";
7
7
  export declare const legacyBaseEsLintFlatConfigFile = "eslint.base.config.js";
8
8
  export declare function isFlatConfig(configFilePath: string): boolean;
9
- export declare function findFlatConfigFile(directory: string, workspaceRoot: string): string | null;
10
- export declare function findOldConfigFile(filePathOrDirectory: string, workspaceRoot: string): string | null;
@@ -2,9 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.legacyBaseEsLintFlatConfigFile = exports.baseEsLintFlatConfigFile = exports.baseEsLintConfigFile = exports.BASE_ESLINT_CONFIG_FILENAMES = exports.ESLINT_CONFIG_FILENAMES = exports.ESLINT_OLD_CONFIG_FILENAMES = exports.ESLINT_FLAT_CONFIG_FILENAMES = void 0;
4
4
  exports.isFlatConfig = isFlatConfig;
5
- exports.findFlatConfigFile = findFlatConfigFile;
6
- exports.findOldConfigFile = findOldConfigFile;
7
- const fs_1 = require("fs");
8
5
  const path_1 = require("path");
9
6
  const flat_config_1 = require("./flat-config");
10
7
  exports.ESLINT_FLAT_CONFIG_FILENAMES = flat_config_1.eslintFlatConfigFilenames;
@@ -22,44 +19,3 @@ function isFlatConfig(configFilePath) {
22
19
  const configFileName = (0, path_1.basename)(configFilePath);
23
20
  return exports.ESLINT_FLAT_CONFIG_FILENAMES.includes(configFileName);
24
21
  }
25
- // https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file-resolution
26
- function findFlatConfigFile(directory, workspaceRoot) {
27
- let currentDir = (0, path_1.resolve)(workspaceRoot, directory);
28
- while (true) {
29
- const configFilePath = getConfigFileInDirectory(currentDir, exports.ESLINT_FLAT_CONFIG_FILENAMES);
30
- if (configFilePath) {
31
- return configFilePath;
32
- }
33
- if (currentDir === workspaceRoot) {
34
- break;
35
- }
36
- currentDir = (0, path_1.dirname)(currentDir);
37
- }
38
- return null;
39
- }
40
- function findOldConfigFile(filePathOrDirectory, workspaceRoot) {
41
- let currentDir = (0, path_1.resolve)(workspaceRoot, filePathOrDirectory);
42
- if (!(0, fs_1.statSync)(currentDir).isDirectory()) {
43
- currentDir = (0, path_1.dirname)(currentDir);
44
- }
45
- while (true) {
46
- const configFilePath = getConfigFileInDirectory(currentDir, exports.ESLINT_OLD_CONFIG_FILENAMES);
47
- if (configFilePath) {
48
- return configFilePath;
49
- }
50
- if (currentDir === workspaceRoot) {
51
- break;
52
- }
53
- currentDir = (0, path_1.dirname)(currentDir);
54
- }
55
- return null;
56
- }
57
- function getConfigFileInDirectory(directory, candidateFileNames) {
58
- for (const filename of candidateFileNames) {
59
- const filePath = (0, path_1.join)(directory, filename);
60
- if ((0, fs_1.existsSync)(filePath)) {
61
- return filePath;
62
- }
63
- }
64
- return null;
65
- }
package/executors.json CHANGED
@@ -1,9 +1,3 @@
1
1
  {
2
- "executors": {
3
- "lint": {
4
- "implementation": "./dist/src/executors/lint/lint.impl",
5
- "schema": "./dist/src/executors/lint/schema.json",
6
- "description": "Run ESLint on a project."
7
- }
8
- }
2
+ "executors": {}
9
3
  }
package/migrations.json CHANGED
@@ -34,6 +34,13 @@
34
34
  "version": "23.1.0-beta.5",
35
35
  "description": "Migrate the removed @typescript-eslint/ban-types rule to its v8 successors (no-empty-object-type, no-unsafe-function-type, no-wrapper-object-types), whose options do not map 1:1 - so it is driven by an AI prompt rather than a deterministic codemod.",
36
36
  "prompt": "./dist/src/migrations/update-23-1-0/migrate-ban-types-rule.md"
37
+ },
38
+ "remove-deprecated-executors": {
39
+ "version": "24.0.0-beta.3",
40
+ "description": "Converts targets using the removed `@nx/eslint` executors to inferred tasks; an AI prompt finishes the targets the converter cannot convert safely and validates the project graph.",
41
+ "implementation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors",
42
+ "prompt": "./dist/src/migrations/update-24-0-0/finish-inferred-conversion.md",
43
+ "documentation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors.md"
37
44
  }
38
45
  },
39
46
  "packageJsonUpdates": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/eslint",
3
- "version": "24.0.0-beta.2",
3
+ "version": "24.0.0-beta.4",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "files": [
@@ -10,7 +10,7 @@
10
10
  "executors.json",
11
11
  "generators.json"
12
12
  ],
13
- "description": "The ESLint plugin for Nx contains executors, generators and utilities used for linting JavaScript/TypeScript projects within an Nx workspace.",
13
+ "description": "The ESLint plugin for Nx infers tasks and provides generators and utilities used for linting JavaScript/TypeScript projects within an Nx workspace.",
14
14
  "repository": {
15
15
  "type": "git",
16
16
  "url": "https://github.com/nrwl/nx.git",
@@ -71,19 +71,19 @@
71
71
  }
72
72
  },
73
73
  "peerDependencies": {
74
- "@nx/jest": "24.0.0-beta.2",
74
+ "@nx/jest": "24.0.0-beta.4",
75
75
  "@zkochan/js-yaml": "0.0.7",
76
76
  "eslint": "^9.0.0 || ^10.0.0"
77
77
  },
78
78
  "dependencies": {
79
- "@nx/devkit": "24.0.0-beta.2",
80
- "@nx/js": "24.0.0-beta.2",
79
+ "@nx/devkit": "24.0.0-beta.4",
80
+ "@nx/js": "24.0.0-beta.4",
81
81
  "semver": "^7.6.3",
82
82
  "tslib": "^2.3.0",
83
83
  "typescript": "~6.0.3"
84
84
  },
85
85
  "devDependencies": {
86
- "nx": "24.0.0-beta.2"
86
+ "nx": "24.0.0-beta.4"
87
87
  },
88
88
  "peerDependenciesMeta": {
89
89
  "@nx/jest": {
@@ -1,5 +0,0 @@
1
- import { type ExecutorContext } from '@nx/devkit';
2
- import type { Schema } from './schema';
3
- export default function run(options: Schema, context: ExecutorContext): Promise<{
4
- success: boolean;
5
- }>;
@@ -1,190 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = run;
4
- const devkit_1 = require("@nx/devkit");
5
- const internal_1 = require("@nx/devkit/internal");
6
- const fs_1 = require("fs");
7
- const path_1 = require("path");
8
- const config_file_1 = require("../../utils/config-file");
9
- const deprecation_1 = require("../../utils/deprecation");
10
- const versions_1 = require("../../utils/versions");
11
- const eslint_utils_1 = require("./utility/eslint-utils");
12
- async function run(options, context) {
13
- (0, deprecation_1.warnEslintExecutorDeprecation)();
14
- // hasTypeAwareRules is deprecated and no longer used, delete it so it's not passed to ESLint
15
- delete options.hasTypeAwareRules;
16
- const systemRoot = context.root;
17
- // eslint resolves files relative to the current working directory.
18
- // We want these paths to always be resolved relative to the workspace
19
- // root to be able to run the lint executor from any subfolder.
20
- process.chdir(systemRoot);
21
- const projectName = context.projectName || '<???>';
22
- const projectRoot = context.projectsConfigurations.projects[context.projectName].root;
23
- const printInfo = options.format && !options.silent;
24
- if (printInfo) {
25
- console.info(`\nLinting ${JSON.stringify(projectName)}...`);
26
- }
27
- options.cacheLocation = options.cacheLocation
28
- ? (0, devkit_1.joinPathFragments)(options.cacheLocation, projectName)
29
- : undefined;
30
- const { printConfig, errorOnUnmatchedPattern, ...normalizedOptions } = options;
31
- // locate the flat config file if it exists starting from the project root
32
- const flatConfigFilePath = (0, config_file_1.findFlatConfigFile)(projectRoot, context.root);
33
- const hasFlatConfig = flatConfigFilePath !== null;
34
- // while standard eslint uses by default closest config to the file, if otherwise not specified,
35
- // the flat config would be resolved starting from the cwd, which we changed to the workspace root
36
- // so we explicitly set the config path to the flat config file path we previously found
37
- if (hasFlatConfig && !normalizedOptions.eslintConfig) {
38
- normalizedOptions.eslintConfig = (0, path_1.relative)(systemRoot, flatConfigFilePath);
39
- }
40
- /**
41
- * We want users to have the option of not specifying the config path, and let
42
- * eslint automatically resolve the `.eslintrc.json` files in each folder.
43
- */
44
- let eslintConfigPath = normalizedOptions.eslintConfig
45
- ? (0, path_1.resolve)(systemRoot, normalizedOptions.eslintConfig)
46
- : undefined;
47
- const { eslint, ESLint } = await (0, eslint_utils_1.resolveAndInstantiateESLint)(eslintConfigPath, normalizedOptions, hasFlatConfig);
48
- (0, internal_1.assertSupportedInstalledPackageVersion)('eslint', versions_1.minSupportedEslintVersion);
49
- if (printConfig) {
50
- try {
51
- const fileConfig = await eslint.calculateConfigForFile(printConfig);
52
- console.log(JSON.stringify(fileConfig, null, ' '));
53
- return {
54
- success: true,
55
- };
56
- }
57
- catch (err) {
58
- console.error(err);
59
- return {
60
- success: false,
61
- };
62
- }
63
- }
64
- let lintResults = [];
65
- const normalizedLintFilePatterns = normalizedOptions.lintFilePatterns.map((pattern) => {
66
- return (0, internal_1.interpolate)(pattern, {
67
- workspaceRoot: '',
68
- projectRoot,
69
- projectName: context.projectName,
70
- });
71
- });
72
- try {
73
- lintResults = await eslint.lintFiles(normalizedLintFilePatterns);
74
- }
75
- catch (err) {
76
- if (err.message.includes('You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser')) {
77
- const ruleName = err.message.match(/rule '([^']+)':/)?.[1];
78
- const reportedFile = err.message.match(/Occurred while linting (.+)$/)?.[1];
79
- let eslintConfigPathForError = `for the project "${projectName}"`;
80
- if (eslintConfigPath) {
81
- eslintConfigPathForError = `"${path_1.posix.relative(context.root, eslintConfigPath)}"`;
82
- }
83
- else {
84
- const configPathForfile = hasFlatConfig
85
- ? (0, config_file_1.findFlatConfigFile)(projectRoot, context.root)
86
- : (0, config_file_1.findOldConfigFile)(reportedFile ?? projectRoot, context.root);
87
- if (configPathForfile) {
88
- eslintConfigPathForError = `"${path_1.posix.relative(context.root, configPathForfile)}"`;
89
- }
90
- }
91
- console.error(`
92
- Error: You have attempted to use ${ruleName ? `the lint rule "${ruleName}"` : 'a lint rule'} which requires the full TypeScript type-checker to be available, but you do not have "parserOptions.project" configured to point at your project tsconfig.json files in the relevant TypeScript file "overrides" block of your ESLint config ${eslintConfigPathForError}
93
- ${reportedFile ? `Occurred while linting ${reportedFile}` : ''}
94
-
95
- Please see https://nx.dev/recipes/tips-n-tricks/eslint for full guidance on how to resolve this issue.
96
- `);
97
- return {
98
- success: false,
99
- };
100
- }
101
- // log unexpected errors
102
- const lines = (err.message ? err.message : err.toString()).split('\n');
103
- const bodyLines = lines.slice(1);
104
- if (err.stack) {
105
- bodyLines.push(...err.stack.split('\n'));
106
- }
107
- devkit_1.output.error({
108
- title: lines[0],
109
- bodyLines,
110
- });
111
- return {
112
- success: false,
113
- };
114
- }
115
- if (lintResults.length === 0 && errorOnUnmatchedPattern) {
116
- const ignoredPatterns = (await Promise.all(normalizedLintFilePatterns.map(async (pattern) => (await eslint.isPathIgnored(pattern)) ? pattern : null)))
117
- .filter((pattern) => !!pattern)
118
- .map((pattern) => `- '${pattern}'`);
119
- if (ignoredPatterns.length) {
120
- const ignoreSection = hasFlatConfig
121
- ? `'ignores' configuration`
122
- : `'.eslintignore' file`;
123
- throw new Error(`All files matching the following patterns are ignored:\n${ignoredPatterns.join('\n')}\n\nPlease check your ${ignoreSection}.`);
124
- }
125
- throw new Error('Invalid lint configuration. Nothing to lint. Please check your lint target pattern(s).');
126
- }
127
- // output fixes to disk, if applicable based on the options
128
- await ESLint.outputFixes(lintResults);
129
- // if quiet, only show errors
130
- if (normalizedOptions.quiet) {
131
- console.debug('Quiet mode enabled - filtering out warnings\n');
132
- lintResults = ESLint.getErrorResults(lintResults);
133
- }
134
- const formatter = await eslint.loadFormatter(normalizedOptions.format);
135
- const formattedResults = await formatter.format(lintResults);
136
- if (normalizedOptions.outputFile) {
137
- const pathToOutputFile = (0, devkit_1.joinPathFragments)(context.root, normalizedOptions.outputFile);
138
- (0, fs_1.mkdirSync)((0, path_1.dirname)(pathToOutputFile), { recursive: true });
139
- (0, fs_1.writeFileSync)(pathToOutputFile, formattedResults);
140
- }
141
- else {
142
- console.info(formattedResults);
143
- }
144
- const totals = getTotals(lintResults);
145
- if (printInfo) {
146
- outputPrintInfo(totals);
147
- }
148
- if (options.maxWarnings >= 0 && totals.warnings > options.maxWarnings) {
149
- console.info(`ESLint found too many warnings (maximum: ${options.maxWarnings}).`);
150
- }
151
- return {
152
- success: normalizedOptions.force ||
153
- (totals.errors === 0 &&
154
- (normalizedOptions.maxWarnings === -1 ||
155
- totals.warnings <= normalizedOptions.maxWarnings)),
156
- };
157
- }
158
- function getTotals(lintResults) {
159
- let errors = 0;
160
- let warnings = 0;
161
- let fixableErrors = 0;
162
- let fixableWarnings = 0;
163
- for (const result of lintResults) {
164
- errors += result.errorCount || 0;
165
- warnings += result.warningCount || 0;
166
- fixableErrors += result.fixableErrorCount || 0;
167
- fixableWarnings += result.fixableWarningCount || 0;
168
- }
169
- return {
170
- errors,
171
- warnings,
172
- fixableErrors,
173
- fixableWarnings,
174
- };
175
- }
176
- function pluralizedOutput(word, count) {
177
- return `${count} ${word}${count === 1 ? '' : 's'}`;
178
- }
179
- function outputPrintInfo({ errors, warnings, fixableErrors, fixableWarnings, }) {
180
- const total = warnings + errors;
181
- const totalFixable = fixableErrors + fixableWarnings;
182
- if (total <= 0) {
183
- console.info('\u2714 All files pass linting\n');
184
- return;
185
- }
186
- console.info(`\u2716 ${pluralizedOutput('problem', total)} (${pluralizedOutput('error', errors)}, ${pluralizedOutput('warning', warnings)})\n`);
187
- if (totalFixable <= 0)
188
- return;
189
- console.info(` ${pluralizedOutput('error', fixableErrors)} and ${pluralizedOutput('warning', fixableWarnings)} are potentially fixable with the \`--fix\` option.\n`);
190
- }
@@ -1,32 +0,0 @@
1
- import type { JsonObject } from '@angular-devkit/core';
2
- import type { Linter } from 'eslint';
3
-
4
- export interface Schema extends JsonObject {
5
- eslintConfig: string | null;
6
- lintFilePatterns: string[];
7
- format: Formatter;
8
- force: boolean;
9
- silent: boolean;
10
- fix: boolean;
11
- cache: boolean;
12
- noEslintrc: boolean;
13
- outputFile: string | null;
14
- cacheLocation: string | null;
15
- maxWarnings: number;
16
- quiet: boolean;
17
- ignorePath: string | null;
18
-
19
- /** @deprecated No longer has any effect. Will be removed in Nx v23. */
20
- hasTypeAwareRules?: boolean;
21
- cacheStrategy: 'content' | 'metadata' | null;
22
- rulesdir: string[];
23
- resolvePluginsRelativeTo: string | null;
24
- reportUnusedDisableDirectives: Linter.StringSeverity | null;
25
- printConfig?: string | null;
26
- errorOnUnmatchedPattern?: boolean;
27
- suppressAll?: boolean;
28
- suppressRule?: string[];
29
- suppressionsLocation?: string;
30
- }
31
-
32
- type Formatter = 'stylish' | 'html' | 'json' | 'json-with-metadata';
@@ -1,154 +0,0 @@
1
- {
2
- "version": 2,
3
- "outputCapture": "direct-nodejs",
4
- "$schema": "https://json-schema.org/schema",
5
- "title": "ESLint Lint Target",
6
- "description": "ESLint Lint Target.",
7
- "cli": "nx",
8
- "type": "object",
9
- "x-deprecated": "The `@nx/eslint:lint` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/eslint:convert-to-inferred` to migrate to the `@nx/eslint/plugin` inferred plugin. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.",
10
- "properties": {
11
- "eslintConfig": {
12
- "type": "string",
13
- "description": "The name of the ESLint configuration file.",
14
- "x-completion-type": "file",
15
- "x-completion-glob": ".eslintrc?(.json)",
16
- "x-priority": "important"
17
- },
18
- "lintFilePatterns": {
19
- "type": "array",
20
- "description": "One or more files/dirs/globs to pass directly to ESLint's `lintFiles()` method.",
21
- "default": ["{projectRoot}"],
22
- "items": {
23
- "type": "string"
24
- }
25
- },
26
- "format": {
27
- "type": "string",
28
- "description": "ESLint Output formatter (https://eslint.org/docs/user-guide/formatters).",
29
- "default": "stylish",
30
- "anyOf": [
31
- {
32
- "enum": ["stylish", "html", "json", "json-with-metadata"]
33
- },
34
- {
35
- "minLength": 1
36
- }
37
- ],
38
- "x-priority": "important"
39
- },
40
- "force": {
41
- "type": "boolean",
42
- "description": "Succeeds even if there was linting errors.",
43
- "default": false
44
- },
45
- "silent": {
46
- "type": "boolean",
47
- "description": "Hide output text.",
48
- "default": false
49
- },
50
- "fix": {
51
- "type": "boolean",
52
- "description": "Fixes linting errors (may overwrite linted files).",
53
- "default": false,
54
- "x-priority": "important"
55
- },
56
- "cache": {
57
- "type": "boolean",
58
- "description": "Only check changed files.",
59
- "default": false
60
- },
61
- "cacheLocation": {
62
- "type": "string",
63
- "description": "Path to the cache file or directory.",
64
- "x-completion-type": "directory",
65
- "x-completion-glob": "tsconfig.*.json"
66
- },
67
- "outputFile": {
68
- "type": "string",
69
- "description": "File to write report to.",
70
- "x-completion-type": "file"
71
- },
72
- "maxWarnings": {
73
- "type": "number",
74
- "description": "Number of warnings to trigger nonzero exit code - default: `-1`.",
75
- "default": -1
76
- },
77
- "quiet": {
78
- "type": "boolean",
79
- "description": "Report errors only - default: `false`.",
80
- "default": false,
81
- "x-priority": "important"
82
- },
83
- "ignorePath": {
84
- "type": "string",
85
- "description": "The path of the `.eslintignore` file. Not supported for Flat Config.",
86
- "x-completion-type": "file",
87
- "x-completion-glob": ".eslintignore"
88
- },
89
- "noEslintrc": {
90
- "type": "boolean",
91
- "description": "The equivalent of the `--no-eslintrc` flag on the ESLint CLI, it is `false` by default.",
92
- "default": false
93
- },
94
- "hasTypeAwareRules": {
95
- "type": "boolean",
96
- "description": "Deprecated. No longer has any effect.",
97
- "x-deprecated": "No longer has any effect. Will be removed in Nx v23."
98
- },
99
- "cacheStrategy": {
100
- "type": "string",
101
- "description": "Strategy to use for detecting changed files in the cache.",
102
- "default": "metadata",
103
- "enum": ["metadata", "content"]
104
- },
105
- "rulesdir": {
106
- "type": "array",
107
- "description": "The equivalent of the `--rulesdir` flag on the ESLint CLI.",
108
- "default": [],
109
- "items": {
110
- "type": "string",
111
- "x-completion-type": "directory"
112
- }
113
- },
114
- "resolvePluginsRelativeTo": {
115
- "type": "string",
116
- "description": "The equivalent of the `--resolve-plugins-relative-to` flag on the ESLint CLI. Not supported for Flat Config.",
117
- "x-completion-type": "directory"
118
- },
119
- "reportUnusedDisableDirectives": {
120
- "type": "string",
121
- "enum": ["off", "warn", "error"],
122
- "description": "The equivalent of the `--report-unused-disable-directives` flag on the ESLint CLI."
123
- },
124
- "printConfig": {
125
- "type": "string",
126
- "description": "The equivalent of the `--print-config` flag on the ESLint CLI.",
127
- "x-completion-type": "file"
128
- },
129
- "errorOnUnmatchedPattern": {
130
- "type": "boolean",
131
- "description": "When set to false, equivalent of the `--no-error-on-unmatched-pattern` flag on the ESLint CLI.",
132
- "default": true
133
- },
134
- "suppressAll": {
135
- "type": "boolean",
136
- "description": "Suppress all existing violations. This is equivalent to the `--suppress-all` flag on the ESLint CLI. Requires ESLint v9.24.0 or higher.",
137
- "default": false
138
- },
139
- "suppressRule": {
140
- "type": "array",
141
- "description": "Suppress violations for specific rules. This is equivalent to the `--suppress-rule` flag on the ESLint CLI. Requires ESLint v9.24.0 or higher.",
142
- "default": [],
143
- "items": {
144
- "type": "string"
145
- }
146
- },
147
- "suppressionsLocation": {
148
- "type": "string",
149
- "description": "Specify the location of the suppressions file. This is equivalent to the `--suppressions-location` flag on the ESLint CLI. Defaults to 'eslint-suppressions.json' in the project root. Requires ESLint v9.24.0 or higher.",
150
- "x-completion-type": "file"
151
- }
152
- },
153
- "examplesFile": "../../../docs/eslint-examples.md"
154
- }
@@ -1,6 +0,0 @@
1
- import type { ESLint } from 'eslint';
2
- import type { Schema } from '../schema';
3
- export declare function resolveAndInstantiateESLint(eslintConfigPath: string | undefined, options: Schema, useFlatConfig?: boolean): Promise<{
4
- ESLint: typeof import("eslint").ESLint;
5
- eslint: ESLint;
6
- }>;
@@ -1,106 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveAndInstantiateESLint = resolveAndInstantiateESLint;
4
- const semver_1 = require("semver");
5
- const config_file_1 = require("../../../utils/config-file");
6
- const resolve_eslint_class_1 = require("../../../utils/resolve-eslint-class");
7
- async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatConfig = false) {
8
- if (useFlatConfig && eslintConfigPath && !(0, config_file_1.isFlatConfig)(eslintConfigPath)) {
9
- throw new Error('When using the new Flat Config with ESLint, all configs must be named eslint.config.js or eslint.config.cjs and .eslintrc files may not be used. See https://eslint.org/docs/latest/use/configure/configuration-files');
10
- }
11
- const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)({
12
- useFlatConfigOverrideVal: useFlatConfig,
13
- });
14
- // Use the broader legacy (eslintrc) options shape so the legacy-only fields
15
- // assigned below type-check. The flat-only fields (ruleFilter, suppress*) are
16
- // intersected in and set conditionally below, since LegacyESLint rejects
17
- // unknown options.
18
- const eslintOptions = {
19
- overrideConfigFile: eslintConfigPath,
20
- fix: !!options.fix &&
21
- (options.quiet ? (message) => message.severity === 2 : true),
22
- cache: !!options.cache,
23
- cacheLocation: options.cacheLocation || undefined,
24
- cacheStrategy: options.cacheStrategy || undefined,
25
- /**
26
- * Default is `true` and if not overridden the eslint.lintFiles() method will throw an error
27
- * when no target files are found.
28
- *
29
- * We don't want ESLint to throw an error if a user has only just created
30
- * a project and therefore doesn't necessarily have matching files, for example.
31
- *
32
- * Also, the angular generator creates a lint pattern for `html` files, but there may
33
- * not be any html files in the project, so keeping it true would break linting every time
34
- */
35
- errorOnUnmatchedPattern: false,
36
- };
37
- if (useFlatConfig) {
38
- if (typeof options.useEslintrc !== 'undefined') {
39
- throw new Error('For Flat Config, the `useEslintrc` option is not applicable. See https://eslint.org/docs/latest/use/configure/configuration-files-new');
40
- }
41
- if (options.resolvePluginsRelativeTo !== undefined) {
42
- throw new Error('For Flat Config, ESLint removed `resolvePluginsRelativeTo` and so it is not supported as an option. See https://eslint.org/docs/latest/use/configure/configuration-files-new');
43
- }
44
- if (options.ignorePath !== undefined) {
45
- 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');
46
- }
47
- if (options.reportUnusedDisableDirectives) {
48
- 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');
49
- }
50
- }
51
- else {
52
- eslintOptions.rulePaths = options.rulesdir || [];
53
- eslintOptions.resolvePluginsRelativeTo =
54
- options.resolvePluginsRelativeTo || undefined;
55
- eslintOptions.ignorePath = options.ignorePath || undefined;
56
- /**
57
- * If "noEslintrc" is set to `true` (and therefore here "useEslintrc" will be `false`), then ESLint will not
58
- * merge the provided config with others it finds automatically.
59
- */
60
- eslintOptions.useEslintrc = !options.noEslintrc;
61
- eslintOptions.reportUnusedDisableDirectives =
62
- options.reportUnusedDisableDirectives || undefined;
63
- }
64
- // `ruleFilter` is flat-config only; LegacyESLint (eslintrc) throws on unknown
65
- // options, so only set it for flat config.
66
- if (options.quiet && useFlatConfig) {
67
- eslintOptions.ruleFilter = (rule) => rule.severity === 2;
68
- }
69
- // Handle bulk suppression options (ESLint v9.24.0+)
70
- try {
71
- if (ESLint.version && (0, semver_1.gte)(ESLint.version, '9.24.0')) {
72
- if (options.suppressAll) {
73
- eslintOptions.suppressAll = true;
74
- }
75
- if (options.suppressRule && options.suppressRule.length > 0) {
76
- eslintOptions.suppressRule = options.suppressRule;
77
- }
78
- if (options.suppressionsLocation) {
79
- eslintOptions.suppressionsLocation = options.suppressionsLocation;
80
- }
81
- }
82
- else if (options.suppressAll ||
83
- (options.suppressRule && options.suppressRule.length > 0) ||
84
- options.suppressionsLocation) {
85
- throw new Error('Bulk suppression options (suppressAll, suppressRule, suppressionsLocation) require ESLint v9.24.0 or higher. Current version: ' +
86
- (ESLint.version || 'unknown'));
87
- }
88
- }
89
- catch (error) {
90
- // If version checking fails (e.g., in tests), skip suppression options
91
- if (options.suppressAll ||
92
- (options.suppressRule && options.suppressRule.length > 0) ||
93
- options.suppressionsLocation) {
94
- // In test environment, just skip the suppression options
95
- console.warn('Bulk suppression options skipped due to version check failure');
96
- }
97
- }
98
- // Runtime ESLint class may be the flat or legacy implementation; the built
99
- // options object is compatible with either at runtime, but the two Options
100
- // shapes diverge in v9 types so cast at the boundary.
101
- const eslint = new ESLint(eslintOptions);
102
- return {
103
- ESLint,
104
- eslint,
105
- };
106
- }
@@ -1,2 +0,0 @@
1
- import { Tree } from '@nx/devkit';
2
- export declare function getEslintTargets(tree: Tree): Set<string>;
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getEslintTargets = getEslintTargets;
4
- const internal_1 = require("@nx/devkit/internal");
5
- function getEslintTargets(tree) {
6
- const eslintTargetNames = new Set();
7
- (0, internal_1.forEachExecutorOptions)(tree, '@nx/eslint:lint', (_, __, target) => {
8
- eslintTargetNames.add(target);
9
- });
10
- (0, internal_1.forEachExecutorOptions)(tree, '@nx/linter:eslint', (_, __, target) => {
11
- eslintTargetNames.add(target);
12
- });
13
- (0, internal_1.forEachExecutorOptions)(tree, '@nrwl/linter:eslint', (_, __, target) => {
14
- eslintTargetNames.add(target);
15
- });
16
- return eslintTargetNames;
17
- }
@@ -1,3 +0,0 @@
1
- export declare const ESLINT_EXECUTOR_DEPRECATION_MESSAGE = "The `@nx/eslint:lint` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/eslint:convert-to-inferred` to migrate to the `@nx/eslint/plugin` inferred targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.";
2
- export declare function warnEslintExecutorDeprecation(): void;
3
- export declare function warnEslintExecutorGenerating(): void;
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ESLINT_EXECUTOR_DEPRECATION_MESSAGE = void 0;
4
- exports.warnEslintExecutorDeprecation = warnEslintExecutorDeprecation;
5
- exports.warnEslintExecutorGenerating = warnEslintExecutorGenerating;
6
- const devkit_1 = require("@nx/devkit");
7
- // TODO(v24): Remove the @nx/eslint:lint executor. The inferred plugin
8
- // (@nx/eslint/plugin) and the convert-to-inferred generator stay supported.
9
- exports.ESLINT_EXECUTOR_DEPRECATION_MESSAGE = 'The `@nx/eslint:lint` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/eslint:convert-to-inferred` to migrate to the `@nx/eslint/plugin` inferred targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.';
10
- function warnEslintExecutorDeprecation() {
11
- devkit_1.logger.warn(exports.ESLINT_EXECUTOR_DEPRECATION_MESSAGE);
12
- }
13
- function warnEslintExecutorGenerating() {
14
- devkit_1.logger.warn('Generating a target that uses the deprecated `@nx/eslint:lint` executor. The executor will be removed in Nx v24. Run `nx g @nx/eslint:convert-to-inferred` next to migrate this target to the `@nx/eslint/plugin` inferred plugin and prevent future generators from emitting executor targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.');
15
- }