@nx/eslint 17.0.3 → 17.0.5

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 (55) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +9 -4
  3. package/generators.json +6 -0
  4. package/migrations.json +68 -0
  5. package/package.json +9 -8
  6. package/plugin.d.ts +1 -0
  7. package/plugin.js +5 -0
  8. package/src/executors/lint/hasher.js +1 -1
  9. package/src/executors/lint/lint.impl.js +67 -33
  10. package/src/executors/lint/schema.d.ts +1 -0
  11. package/src/executors/lint/schema.json +7 -3
  12. package/src/executors/lint/utility/eslint-utils.js +5 -1
  13. package/src/generators/convert-to-flat-config/converters/json-converter.d.ts +6 -1
  14. package/src/generators/convert-to-flat-config/converters/json-converter.js +28 -33
  15. package/src/generators/convert-to-flat-config/generator.js +73 -17
  16. package/src/generators/convert-to-flat-config/schema.json +1 -1
  17. package/src/generators/init/global-eslint-config.js +9 -5
  18. package/src/generators/init/init-migration.d.ts +1 -1
  19. package/src/generators/init/init-migration.js +53 -14
  20. package/src/generators/init/init.d.ts +5 -5
  21. package/src/generators/init/init.js +63 -35
  22. package/src/generators/init/schema.json +28 -0
  23. package/src/generators/lint-project/lint-project.d.ts +9 -3
  24. package/src/generators/lint-project/lint-project.js +76 -40
  25. package/src/generators/lint-project/setup-root-eslint.d.ts +7 -0
  26. package/src/generators/lint-project/setup-root-eslint.js +33 -0
  27. package/src/generators/utils/eslint-file.d.ts +2 -5
  28. package/src/generators/utils/eslint-file.js +37 -30
  29. package/src/generators/utils/flat-config/ast-utils.d.ts +4 -5
  30. package/src/generators/utils/flat-config/ast-utils.js +35 -38
  31. package/src/generators/utils/flat-config/path-utils.d.ts +2 -1
  32. package/src/generators/utils/flat-config/path-utils.js +9 -12
  33. package/src/generators/utils/plugin.d.ts +2 -0
  34. package/src/generators/utils/plugin.js +11 -0
  35. package/src/generators/workspace-rule/files/__name__.ts__tmpl__ +2 -2
  36. package/src/generators/workspace-rule/schema.json +1 -1
  37. package/src/generators/workspace-rule/workspace-rule.js +7 -2
  38. package/src/generators/workspace-rules-project/files/tsconfig.json__tmpl__ +2 -1
  39. package/src/generators/workspace-rules-project/schema.json +1 -1
  40. package/src/generators/workspace-rules-project/workspace-rules-project.d.ts +3 -2
  41. package/src/generators/workspace-rules-project/workspace-rules-project.js +11 -9
  42. package/src/migrations/update-15-0-0/add-eslint-inputs.js +2 -2
  43. package/src/migrations/update-15-7-1/add-eslint-ignore.js +2 -2
  44. package/src/migrations/update-17-1-0/update-typescript-eslint.d.ts +2 -0
  45. package/src/migrations/update-17-1-0/update-typescript-eslint.js +74 -0
  46. package/src/migrations/update-17-2-0/simplify-eslint-patterns.d.ts +2 -0
  47. package/src/migrations/update-17-2-0/simplify-eslint-patterns.js +46 -0
  48. package/src/migrations/update-17-2-9/move-options-to-target-defaults.d.ts +2 -0
  49. package/src/migrations/update-17-2-9/move-options-to-target-defaults.js +107 -0
  50. package/src/plugins/plugin.d.ts +6 -0
  51. package/src/plugins/plugin.js +117 -0
  52. package/src/utils/config-file.d.ts +4 -0
  53. package/src/utils/config-file.js +18 -0
  54. package/src/utils/versions.d.ts +2 -2
  55. package/src/utils/versions.js +2 -2
@@ -3,21 +3,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.convertToFlatConfigGenerator = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const eslint_file_1 = require("../utils/eslint-file");
6
+ const path_1 = require("path");
7
+ const versions_1 = require("../../utils/versions");
6
8
  const json_converter_1 = require("./converters/json-converter");
9
+ const js_yaml_1 = require("js-yaml");
7
10
  async function convertToFlatConfigGenerator(tree, options) {
8
11
  const eslintFile = (0, eslint_file_1.findEslintFile)(tree);
9
12
  if (!eslintFile) {
10
13
  throw new Error('Could not find root eslint file');
11
14
  }
12
- if (!eslintFile.endsWith('.json')) {
13
- throw new Error('Only json eslint config files are supported for conversion');
15
+ if (eslintFile.endsWith('.js')) {
16
+ throw new Error('Only json and yaml eslint config files are supported for conversion');
14
17
  }
15
- // rename root eslint config to eslint.config.js
18
+ const eslintIgnoreFiles = new Set(['.eslintignore']);
19
+ // convert root eslint config to eslint.config.js
16
20
  convertRootToFlatConfig(tree, eslintFile);
17
- // rename and map files
21
+ // convert project eslint files to eslint.config.js
18
22
  const projects = (0, devkit_1.getProjects)(tree);
19
23
  for (const [project, projectConfig] of projects) {
20
- convertProjectToFlatConfig(tree, project, projectConfig, (0, devkit_1.readNxJson)(tree));
24
+ convertProjectToFlatConfig(tree, project, projectConfig, (0, devkit_1.readNxJson)(tree), eslintIgnoreFiles);
25
+ }
26
+ // delete all .eslintignore files
27
+ for (const ignoreFile of eslintIgnoreFiles) {
28
+ tree.delete(ignoreFile);
21
29
  }
22
30
  // replace references in nx.json
23
31
  updateNxJsonConfig(tree);
@@ -29,27 +37,42 @@ async function convertToFlatConfigGenerator(tree, options) {
29
37
  exports.convertToFlatConfigGenerator = convertToFlatConfigGenerator;
30
38
  exports.default = convertToFlatConfigGenerator;
31
39
  function convertRootToFlatConfig(tree, eslintFile) {
32
- if (eslintFile.endsWith('.base.json')) {
33
- convertConfigToFlatConfig(tree, '', '.eslintrc.base.json', 'eslint.base.config.js');
40
+ if (/\.base\.(js|json|yml|yaml)$/.test(eslintFile)) {
41
+ convertConfigToFlatConfig(tree, '', eslintFile, 'eslint.base.config.js');
34
42
  }
35
- convertConfigToFlatConfig(tree, '', '.eslintrc.json', 'eslint.config.js');
43
+ convertConfigToFlatConfig(tree, '', eslintFile.replace('.base.', '.'), 'eslint.config.js');
36
44
  }
37
- function convertProjectToFlatConfig(tree, project, projectConfig, nxJson) {
38
- if (tree.exists(`${projectConfig.root}/.eslintrc.json`)) {
45
+ function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslintIgnoreFiles) {
46
+ const eslintFile = (0, eslint_file_1.findEslintFile)(tree, projectConfig.root);
47
+ if (eslintFile && !eslintFile.endsWith('.js')) {
39
48
  if (projectConfig.targets) {
40
- 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'));
51
+ let ignorePath;
41
52
  for (const target of eslintTargets) {
42
53
  // remove any obsolete `eslintConfig` options pointing to the old config file
43
54
  if (projectConfig.targets[target].options?.eslintConfig) {
44
55
  delete projectConfig.targets[target].options.eslintConfig;
45
56
  }
57
+ if (projectConfig.targets[target].options?.ignorePath) {
58
+ ignorePath = projectConfig.targets[target].options.ignorePath;
59
+ delete projectConfig.targets[target].options.ignorePath;
60
+ }
46
61
  (0, devkit_1.updateProjectConfiguration)(tree, project, projectConfig);
47
62
  }
48
- const nxHasLintTargets = Object.keys(nxJson.targetDefaults || {}).some((t) => (t === '@nx/eslint:lint' ||
49
- 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')) &&
50
66
  projectConfig.targets?.[t]);
51
- if (nxHasLintTargets || eslintTargets.length > 0) {
52
- convertConfigToFlatConfig(tree, projectConfig.root, '.eslintrc.json', 'eslint.config.js');
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) {
71
+ convertConfigToFlatConfig(tree, projectConfig.root, eslintFile, 'eslint.config.js', ignorePath);
72
+ eslintIgnoreFiles.add(`${projectConfig.root}/.eslintignore`);
73
+ if (ignorePath) {
74
+ eslintIgnoreFiles.add(ignorePath);
75
+ }
53
76
  }
54
77
  }
55
78
  }
@@ -78,6 +101,39 @@ function updateNxJsonConfig(tree) {
78
101
  });
79
102
  }
80
103
  }
81
- function convertConfigToFlatConfig(tree, root, source, target) {
82
- (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, source, target);
104
+ function convertConfigToFlatConfig(tree, root, source, target, ignorePath) {
105
+ const ignorePaths = ignorePath
106
+ ? [ignorePath, `${root}/.eslintignore`]
107
+ : [`${root}/.eslintignore`];
108
+ if (source.endsWith('.json')) {
109
+ const config = (0, devkit_1.readJson)(tree, `${root}/${source}`);
110
+ const conversionResult = (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, config, ignorePaths);
111
+ return processConvertedConfig(tree, root, source, target, conversionResult);
112
+ }
113
+ if (source.endsWith('.yaml') || source.endsWith('.yml')) {
114
+ const originalContent = tree.read(`${root}/${source}`, 'utf-8');
115
+ const config = (0, js_yaml_1.load)(originalContent, {
116
+ json: true,
117
+ filename: source,
118
+ });
119
+ const conversionResult = (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, config, ignorePaths);
120
+ return processConvertedConfig(tree, root, source, target, conversionResult);
121
+ }
122
+ }
123
+ function processConvertedConfig(tree, root, source, target, { content, addESLintRC, addESLintJS, }) {
124
+ // remove original config file
125
+ tree.delete((0, path_1.join)(root, source));
126
+ // save new
127
+ tree.write((0, path_1.join)(root, target), content);
128
+ // add missing packages
129
+ if (addESLintRC) {
130
+ (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
131
+ '@eslint/eslintrc': versions_1.eslintrcVersion,
132
+ });
133
+ }
134
+ if (addESLintJS) {
135
+ (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
136
+ '@eslint/js': versions_1.eslintVersion,
137
+ });
138
+ }
83
139
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "ConvertToFlatConfig",
4
4
  "cli": "nx",
5
5
  "description": "Convert an Nx workspace's ESLint configs to use Flat Config.",
@@ -80,19 +80,23 @@ const getGlobalEsLintConfiguration = (unitTestRunner, rootProject) => {
80
80
  exports.getGlobalEsLintConfiguration = getGlobalEsLintConfiguration;
81
81
  const getGlobalFlatEslintConfiguration = (unitTestRunner, rootProject) => {
82
82
  const nodeList = (0, ast_utils_1.createNodeList)(new Map(), [], true);
83
- let content = (0, ast_utils_1.stringifyNodeList)(nodeList, '', 'eslint.config.js');
83
+ let content = (0, ast_utils_1.stringifyNodeList)(nodeList);
84
84
  content = (0, ast_utils_1.addImportToFlatConfig)(content, 'nxPlugin', '@nx/eslint-plugin');
85
85
  content = (0, ast_utils_1.addPluginsToExportsBlock)(content, [
86
86
  { name: '@nx', varName: 'nxPlugin', imp: '@nx/eslint-plugin' },
87
87
  ]);
88
88
  if (!rootProject) {
89
- content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(moduleBoundariesOverride, ''));
89
+ content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(moduleBoundariesOverride));
90
90
  }
91
- content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(exports.typeScriptOverride, ''));
92
- content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(exports.javaScriptOverride, ''));
91
+ content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(exports.typeScriptOverride));
92
+ content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(exports.javaScriptOverride));
93
93
  if (unitTestRunner === 'jest') {
94
- content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(jestOverride, ''));
94
+ content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(jestOverride));
95
95
  }
96
+ // add ignore for .nx folder
97
+ content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateAst)({
98
+ ignores: ['.nx'],
99
+ }));
96
100
  return content;
97
101
  };
98
102
  exports.getGlobalFlatEslintConfiguration = getGlobalFlatEslintConfiguration;
@@ -1,3 +1,3 @@
1
1
  import { ProjectConfiguration, TargetConfiguration, Tree } from '@nx/devkit';
2
- export declare function migrateConfigToMonorepoStyle(projects: ProjectConfiguration[], tree: Tree, unitTestRunner: string): void;
2
+ export declare function migrateConfigToMonorepoStyle(projects: ProjectConfiguration[], tree: Tree, unitTestRunner: string, keepExistingVersions?: boolean): void;
3
3
  export declare function findLintTarget(project: ProjectConfiguration): TargetConfiguration;
@@ -8,24 +8,58 @@ 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
- function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner) {
12
- if ((0, flat_config_1.useFlatConfig)(tree)) {
13
- // we need this for the compat
14
- (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
15
- '@eslint/js': versions_1.eslintVersion,
16
- });
17
- tree.write('eslint.base.config.js', (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(unitTestRunner));
11
+ const plugin_1 = require("../utils/plugin");
12
+ const config_file_1 = require("../../utils/config-file");
13
+ function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, keepExistingVersions) {
14
+ const rootEslintConfig = (0, eslint_file_1.findEslintFile)(tree);
15
+ let skipCleanup = false;
16
+ if (rootEslintConfig?.match(/\.base\./) &&
17
+ !projects.some((p) => p.root === '.')) {
18
+ // if the migration has been run already, we need to rename the base config
19
+ // and only update the extends paths
20
+ tree.rename(rootEslintConfig, rootEslintConfig.replace('.base.', '.'));
21
+ skipCleanup = true;
18
22
  }
19
23
  else {
20
- (0, devkit_1.writeJson)(tree, '.eslintrc.base.json', (0, global_eslint_config_1.getGlobalEsLintConfiguration)(unitTestRunner));
24
+ if ((0, flat_config_1.useFlatConfig)(tree)) {
25
+ // we need this for the compat
26
+ (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
27
+ '@eslint/js': versions_1.eslintVersion,
28
+ }, undefined, keepExistingVersions);
29
+ tree.write(tree.exists('eslint.config.js')
30
+ ? 'eslint.base.config.js'
31
+ : 'eslint.config.js', (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(unitTestRunner));
32
+ }
33
+ else {
34
+ const eslintFile = (0, eslint_file_1.findEslintFile)(tree, '.');
35
+ (0, devkit_1.writeJson)(tree, eslintFile ? '.eslintrc.base.json' : '.eslintrc.json', (0, global_eslint_config_1.getGlobalEsLintConfiguration)(unitTestRunner));
36
+ }
21
37
  }
22
- // update extens in all projects' eslint configs
38
+ // update extends in all projects' eslint configs
23
39
  projects.forEach((project) => {
40
+ let eslintFile;
24
41
  const lintTarget = findLintTarget(project);
25
42
  if (lintTarget) {
26
- const eslintFile = lintTarget.options.eslintConfig || (0, eslint_file_1.findEslintFile)(tree, project.root);
27
- if (eslintFile) {
28
- const projectEslintPath = (0, devkit_1.joinPathFragments)(project.root, eslintFile);
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;
53
+ }
54
+ }
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 {
29
63
  migrateEslintFile(projectEslintPath, tree);
30
64
  }
31
65
  }
@@ -39,13 +73,14 @@ function findLintTarget(project) {
39
73
  }
40
74
  exports.findLintTarget = findLintTarget;
41
75
  function migrateEslintFile(projectEslintPath, tree) {
76
+ const baseFile = (0, eslint_file_1.findEslintFile)(tree);
42
77
  if ((0, eslint_file_1.isEslintConfigSupported)(tree)) {
43
78
  if ((0, flat_config_1.useFlatConfig)(tree)) {
44
79
  let config = tree.read(projectEslintPath, 'utf-8');
45
80
  // remove @nx plugin
46
81
  config = (0, ast_utils_1.removePlugin)(config, '@nx', '@nx/eslint-plugin-nx');
47
82
  // extend eslint.base.config.js
48
- config = (0, ast_utils_1.addImportToFlatConfig)(config, 'baseConfig', `${(0, devkit_1.offsetFromRoot)((0, path_1.dirname)(projectEslintPath))}eslint.base.config.js`);
83
+ config = (0, ast_utils_1.addImportToFlatConfig)(config, 'baseConfig', `${(0, devkit_1.offsetFromRoot)((0, path_1.dirname)(projectEslintPath))}${baseFile}`);
49
84
  config = (0, ast_utils_1.addBlockToFlatConfigExport)(config, (0, ast_utils_1.generateSpreadElement)('baseConfig'), { insertAtTheEnd: false });
50
85
  // cleanup file extends
51
86
  config = (0, ast_utils_1.removeCompatExtends)(config, [
@@ -69,7 +104,11 @@ function migrateEslintFile(projectEslintPath, tree) {
69
104
  }
70
105
  // add extends
71
106
  json.extends = json.extends || [];
72
- const pathToRootConfig = `${(0, devkit_1.offsetFromRoot)((0, path_1.dirname)(projectEslintPath))}.eslintrc.base.json`;
107
+ // ensure extends is an array
108
+ if (typeof json.extends === 'string') {
109
+ json.extends = [json.extends];
110
+ }
111
+ const pathToRootConfig = `${(0, devkit_1.offsetFromRoot)((0, path_1.dirname)(projectEslintPath))}${baseFile}`;
73
112
  if (json.extends.indexOf(pathToRootConfig) === -1) {
74
113
  json.extends.push(pathToRootConfig);
75
114
  }
@@ -1,9 +1,9 @@
1
1
  import type { GeneratorCallback, Tree } from '@nx/devkit';
2
- import { Linter } from '../utils/linter';
3
2
  export interface LinterInitOptions {
4
- linter?: Linter;
5
- unitTestRunner?: string;
6
3
  skipPackageJson?: boolean;
7
- rootProject?: boolean;
4
+ keepExistingVersions?: boolean;
5
+ updatePackageScripts?: boolean;
6
+ addPlugin?: boolean;
8
7
  }
9
- export declare function lintInitGenerator(tree: Tree, options: LinterInitOptions): GeneratorCallback;
8
+ export declare function initEsLint(tree: Tree, options: LinterInitOptions): Promise<GeneratorCallback>;
9
+ export declare function lintInitGenerator(tree: Tree, options: LinterInitOptions): Promise<GeneratorCallback>;
@@ -1,23 +1,29 @@
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
+ const update_package_scripts_1 = require("@nx/devkit/src/utils/update-package-scripts");
5
6
  const versions_1 = require("../../utils/versions");
6
7
  const eslint_file_1 = require("../utils/eslint-file");
7
- const global_eslint_config_1 = require("./global-eslint-config");
8
- function addTargetDefaults(tree) {
8
+ const plugin_1 = require("../../plugins/plugin");
9
+ const plugin_2 = require("../utils/plugin");
10
+ function updateProductionFileset(tree) {
9
11
  const nxJson = (0, devkit_1.readNxJson)(tree);
10
12
  const productionFileSet = nxJson.namedInputs?.production;
11
13
  if (productionFileSet) {
12
- // Remove .eslintrc.json
13
14
  productionFileSet.push('!{projectRoot}/.eslintrc.json');
14
15
  productionFileSet.push('!{projectRoot}/eslint.config.js');
15
16
  // Dedupe and set
16
17
  nxJson.namedInputs.production = Array.from(new Set(productionFileSet));
17
18
  }
19
+ (0, devkit_1.updateNxJson)(tree, nxJson);
20
+ }
21
+ function addTargetDefaults(tree) {
22
+ const nxJson = (0, devkit_1.readNxJson)(tree);
18
23
  nxJson.targetDefaults ??= {};
19
- nxJson.targetDefaults.lint ??= {};
20
- nxJson.targetDefaults.lint.inputs ??= [
24
+ nxJson.targetDefaults['@nx/eslint:lint'] ??= {};
25
+ nxJson.targetDefaults['@nx/eslint:lint'].cache ??= true;
26
+ nxJson.targetDefaults['@nx/eslint:lint'].inputs ??= [
21
27
  'default',
22
28
  `{workspaceRoot}/.eslintrc.json`,
23
29
  `{workspaceRoot}/.eslintignore`,
@@ -25,41 +31,63 @@ function addTargetDefaults(tree) {
25
31
  ];
26
32
  (0, devkit_1.updateNxJson)(tree, nxJson);
27
33
  }
28
- /**
29
- * Initializes ESLint configuration in a workspace and adds necessary dependencies.
30
- */
31
- function initEsLint(tree, options) {
32
- if ((0, eslint_file_1.findEslintFile)(tree)) {
34
+ function addPlugin(tree) {
35
+ const nxJson = (0, devkit_1.readNxJson)(tree);
36
+ nxJson.plugins ??= [];
37
+ for (const plugin of nxJson.plugins) {
38
+ if (typeof plugin === 'string'
39
+ ? plugin === '@nx/eslint/plugin'
40
+ : plugin.plugin === '@nx/eslint/plugin') {
41
+ return;
42
+ }
43
+ }
44
+ nxJson.plugins.push({
45
+ plugin: '@nx/eslint/plugin',
46
+ options: {
47
+ targetName: 'lint',
48
+ },
49
+ });
50
+ (0, devkit_1.updateNxJson)(tree, nxJson);
51
+ }
52
+ async function initEsLint(tree, options) {
53
+ const nxJson = (0, devkit_1.readNxJson)(tree);
54
+ const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
55
+ nxJson.useInferencePlugins !== false;
56
+ options.addPlugin ??= addPluginDefault;
57
+ const hasPlugin = (0, plugin_2.hasEslintPlugin)(tree);
58
+ const rootEslintFile = (0, eslint_file_1.findEslintFile)(tree);
59
+ if (rootEslintFile && options.addPlugin && !hasPlugin) {
60
+ addPlugin(tree);
61
+ if (options.updatePackageScripts) {
62
+ await (0, update_package_scripts_1.updatePackageScripts)(tree, plugin_1.createNodes);
63
+ }
33
64
  return () => { };
34
65
  }
35
- if (!options.skipPackageJson) {
36
- (0, devkit_1.removeDependenciesFromPackageJson)(tree, ['@nx/eslint'], []);
66
+ if (rootEslintFile) {
67
+ return () => { };
37
68
  }
38
- (0, devkit_1.writeJson)(tree, '.eslintrc.json', (0, global_eslint_config_1.getGlobalEsLintConfiguration)(options.unitTestRunner, options.rootProject));
39
- tree.write('.eslintignore', 'node_modules\n');
40
- addTargetDefaults(tree);
41
- if (tree.exists('.vscode/extensions.json')) {
42
- (0, devkit_1.updateJson)(tree, '.vscode/extensions.json', (json) => {
43
- json.recommendations ||= [];
44
- const extension = 'dbaeumer.vscode-eslint';
45
- if (!json.recommendations.includes(extension)) {
46
- json.recommendations.push(extension);
47
- }
48
- return json;
49
- });
69
+ updateProductionFileset(tree);
70
+ if (options.addPlugin) {
71
+ addPlugin(tree);
50
72
  }
51
- return !options.skipPackageJson
52
- ? (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
73
+ else {
74
+ addTargetDefaults(tree);
75
+ }
76
+ const tasks = [];
77
+ if (!options.skipPackageJson) {
78
+ tasks.push((0, devkit_1.removeDependenciesFromPackageJson)(tree, ['@nx/eslint'], []));
79
+ tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
53
80
  '@nx/eslint': versions_1.nxVersion,
54
- '@nx/eslint-plugin': versions_1.nxVersion,
55
- '@typescript-eslint/parser': versions_1.typescriptESLintVersion,
56
- '@typescript-eslint/eslint-plugin': versions_1.typescriptESLintVersion,
57
81
  eslint: versions_1.eslintVersion,
58
- 'eslint-config-prettier': versions_1.eslintConfigPrettierVersion,
59
- })
60
- : () => { };
82
+ }, undefined, options.keepExistingVersions));
83
+ }
84
+ if (options.updatePackageScripts) {
85
+ await (0, update_package_scripts_1.updatePackageScripts)(tree, plugin_1.createNodes);
86
+ }
87
+ return (0, devkit_1.runTasksInSerial)(...tasks);
61
88
  }
62
- function lintInitGenerator(tree, options) {
63
- return initEsLint(tree, options);
89
+ exports.initEsLint = initEsLint;
90
+ async function lintInitGenerator(tree, options) {
91
+ return await initEsLint(tree, { addPlugin: false, ...options });
64
92
  }
65
93
  exports.lintInitGenerator = lintInitGenerator;
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "cli": "nx",
4
+ "$id": "NxESLintInit",
5
+ "title": "Initialize ESLint Plugin",
6
+ "description": "Set up the ESLint plugin.",
7
+ "type": "object",
8
+ "properties": {
9
+ "skipPackageJson": {
10
+ "description": "Do not add dependencies to `package.json`.",
11
+ "type": "boolean",
12
+ "default": false
13
+ },
14
+ "keepExistingVersions": {
15
+ "type": "boolean",
16
+ "x-priority": "internal",
17
+ "description": "Keep existing dependencies versions",
18
+ "default": false
19
+ },
20
+ "updatePackageScripts": {
21
+ "type": "boolean",
22
+ "x-priority": "internal",
23
+ "description": "Update `package.json` scripts with inferred targets",
24
+ "default": false
25
+ }
26
+ },
27
+ "required": []
28
+ }
@@ -1,4 +1,4 @@
1
- import type { Tree } from '@nx/devkit';
1
+ import type { GeneratorCallback, Tree } from '@nx/devkit';
2
2
  import { Linter as LinterEnum } from '../utils/linter';
3
3
  interface LintProjectOptions {
4
4
  project: string;
@@ -10,7 +10,13 @@ interface LintProjectOptions {
10
10
  skipPackageJson?: boolean;
11
11
  unitTestRunner?: string;
12
12
  rootProject?: boolean;
13
+ keepExistingVersions?: boolean;
14
+ addPlugin?: boolean;
15
+ /**
16
+ * @internal
17
+ */
18
+ addExplicitTargets?: boolean;
13
19
  }
14
- export declare function mapLintPattern(projectRoot: string, extension: string, rootProject?: boolean): string;
15
- export declare function lintProjectGenerator(tree: Tree, options: LintProjectOptions): Promise<import("@nx/devkit").GeneratorCallback>;
20
+ export declare function lintProjectGenerator(tree: Tree, options: LintProjectOptions): Promise<GeneratorCallback>;
21
+ export declare function lintProjectGeneratorInternal(tree: Tree, options: LintProjectOptions): Promise<GeneratorCallback>;
16
22
  export {};