@nx/eslint 20.4.0-beta.1 → 20.4.0-beta.2

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/eslint",
3
- "version": "20.4.0-beta.1",
3
+ "version": "20.4.0-beta.2",
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": {
@@ -35,8 +35,8 @@
35
35
  "eslint": "^8.0.0 || ^9.0.0"
36
36
  },
37
37
  "dependencies": {
38
- "@nx/devkit": "20.4.0-beta.1",
39
- "@nx/js": "20.4.0-beta.1",
38
+ "@nx/devkit": "20.4.0-beta.2",
39
+ "@nx/js": "20.4.0-beta.2",
40
40
  "semver": "^7.5.3",
41
41
  "tslib": "^2.3.0",
42
42
  "typescript": "~5.7.2"
@@ -4,7 +4,7 @@ import { ESLint } from 'eslint';
4
4
  * Converts an ESLint JSON config to a flat config.
5
5
  * Deletes the original file along with .eslintignore if it exists.
6
6
  */
7
- export declare function convertEslintJsonToFlatConfig(tree: Tree, root: string, config: ESLint.ConfigData, ignorePaths: string[]): {
7
+ export declare function convertEslintJsonToFlatConfig(tree: Tree, root: string, config: ESLint.ConfigData, ignorePaths: string[], format: 'cjs' | 'mjs'): {
8
8
  content: string;
9
9
  addESLintRC: boolean;
10
10
  addESLintJS: boolean;
@@ -10,7 +10,7 @@ const path_utils_1 = require("../../utils/flat-config/path-utils");
10
10
  * Converts an ESLint JSON config to a flat config.
11
11
  * Deletes the original file along with .eslintignore if it exists.
12
12
  */
13
- function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths) {
13
+ function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths, format) {
14
14
  const importsMap = new Map();
15
15
  const exportElements = [];
16
16
  let isFlatCompatNeeded = false;
@@ -22,7 +22,7 @@ function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths) {
22
22
  ignores: ['**/dist'],
23
23
  }));
24
24
  if (config.extends) {
25
- const extendsResult = addExtends(importsMap, exportElements, config);
25
+ const extendsResult = addExtends(importsMap, exportElements, config, format);
26
26
  isFlatCompatNeeded = extendsResult.isFlatCompatNeeded;
27
27
  isESLintJSNeeded = extendsResult.isESLintJSNeeded;
28
28
  }
@@ -74,7 +74,7 @@ function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths) {
74
74
  override.parser) {
75
75
  isFlatCompatNeeded = true;
76
76
  }
77
- exportElements.push((0, ast_utils_1.generateFlatOverride)(override));
77
+ exportElements.push((0, ast_utils_1.generateFlatOverride)(override, format));
78
78
  });
79
79
  }
80
80
  if (config.ignorePatterns) {
@@ -100,7 +100,7 @@ function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths) {
100
100
  }
101
101
  }
102
102
  // create the node list and print it to new file
103
- const nodeList = (0, ast_utils_1.createNodeList)(importsMap, exportElements);
103
+ const nodeList = (0, ast_utils_1.createNodeList)(importsMap, exportElements, format);
104
104
  let content = (0, ast_utils_1.stringifyNodeList)(nodeList);
105
105
  if (isFlatCompatNeeded) {
106
106
  content = (0, ast_utils_1.addFlatCompatToFlatConfig)(content);
@@ -112,7 +112,7 @@ function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths) {
112
112
  };
113
113
  }
114
114
  // add parsed extends to export blocks and add import statements
115
- function addExtends(importsMap, configBlocks, config) {
115
+ function addExtends(importsMap, configBlocks, config, format) {
116
116
  let isFlatCompatNeeded = false;
117
117
  let isESLintJSNeeded = false;
118
118
  const extendsConfig = Array.isArray(config.extends)
@@ -126,7 +126,7 @@ function addExtends(importsMap, configBlocks, config) {
126
126
  if (imp.match(/\.eslintrc(.base)?\.json$/)) {
127
127
  const localName = index ? `baseConfig${index}` : 'baseConfig';
128
128
  configBlocks.push((0, ast_utils_1.generateSpreadElement)(localName));
129
- const newImport = imp.replace(/^(.*)\.eslintrc(.base)?\.json$/, '$1eslint$2.config.cjs');
129
+ const newImport = imp.replace(/^(.*)\.eslintrc(.base)?\.json$/, `$1eslint$2.config.${format}`);
130
130
  importsMap.set(newImport, localName);
131
131
  }
132
132
  else {
@@ -14,20 +14,21 @@ async function convertToFlatConfigGenerator(tree, options) {
14
14
  if (eslintFile.endsWith('.js')) {
15
15
  throw new Error('Only json and yaml eslint config files are supported for conversion');
16
16
  }
17
+ options.eslintConfigFormat ??= 'mjs';
17
18
  const eslintIgnoreFiles = new Set(['.eslintignore']);
18
- // convert root eslint config to eslint.config.cjs
19
- convertRootToFlatConfig(tree, eslintFile);
19
+ // convert root eslint config to eslint.config.cjs or eslint.base.config.mjs based on eslintConfigFormat
20
+ convertRootToFlatConfig(tree, eslintFile, options.eslintConfigFormat);
20
21
  // convert project eslint files to eslint.config.cjs
21
22
  const projects = (0, devkit_1.getProjects)(tree);
22
23
  for (const [project, projectConfig] of projects) {
23
- convertProjectToFlatConfig(tree, project, projectConfig, (0, devkit_1.readNxJson)(tree), eslintIgnoreFiles);
24
+ convertProjectToFlatConfig(tree, project, projectConfig, (0, devkit_1.readNxJson)(tree), eslintIgnoreFiles, options.eslintConfigFormat);
24
25
  }
25
26
  // delete all .eslintignore files
26
27
  for (const ignoreFile of eslintIgnoreFiles) {
27
28
  tree.delete(ignoreFile);
28
29
  }
29
30
  // replace references in nx.json
30
- updateNxJsonConfig(tree);
31
+ updateNxJsonConfig(tree, options.eslintConfigFormat);
31
32
  // install missing packages
32
33
  if (!options.skipFormat) {
33
34
  await (0, devkit_1.formatFiles)(tree);
@@ -35,13 +36,13 @@ async function convertToFlatConfigGenerator(tree, options) {
35
36
  return () => (0, devkit_1.installPackagesTask)(tree);
36
37
  }
37
38
  exports.default = convertToFlatConfigGenerator;
38
- function convertRootToFlatConfig(tree, eslintFile) {
39
+ function convertRootToFlatConfig(tree, eslintFile, format) {
39
40
  if (/\.base\.(js|json|yml|yaml)$/.test(eslintFile)) {
40
- convertConfigToFlatConfig(tree, '', eslintFile, 'eslint.base.config.cjs');
41
+ convertConfigToFlatConfig(tree, '', eslintFile, `eslint.base.config.${format}`, format);
41
42
  }
42
- convertConfigToFlatConfig(tree, '', eslintFile.replace('.base.', '.'), 'eslint.config.cjs');
43
+ convertConfigToFlatConfig(tree, '', eslintFile.replace('.base.', '.'), `eslint.config.${format}`, format);
43
44
  }
44
- function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslintIgnoreFiles) {
45
+ function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslintIgnoreFiles, format) {
45
46
  const eslintFile = (0, eslint_file_1.findEslintFile)(tree, projectConfig.root);
46
47
  if (eslintFile && !eslintFile.endsWith('.js')) {
47
48
  if (projectConfig.targets) {
@@ -67,7 +68,7 @@ function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslint
67
68
  ? p === '@nx/eslint/plugin'
68
69
  : p.plugin === '@nx/eslint/plugin');
69
70
  if (nxHasEsLintTargets || nxHasEsLintPlugin || eslintTargets.length > 0) {
70
- convertConfigToFlatConfig(tree, projectConfig.root, eslintFile, 'eslint.config.cjs', ignorePath);
71
+ convertConfigToFlatConfig(tree, projectConfig.root, eslintFile, `eslint.config.${format}`, format, ignorePath);
71
72
  eslintIgnoreFiles.add(`${projectConfig.root}/.eslintignore`);
72
73
  if (ignorePath) {
73
74
  eslintIgnoreFiles.add(ignorePath);
@@ -78,35 +79,35 @@ function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslint
78
79
  }
79
80
  // update names of eslint files in nx.json
80
81
  // and remove eslintignore
81
- function updateNxJsonConfig(tree) {
82
+ function updateNxJsonConfig(tree, format) {
82
83
  if (tree.exists('nx.json')) {
83
84
  (0, devkit_1.updateJson)(tree, 'nx.json', (json) => {
84
85
  if (json.targetDefaults?.lint?.inputs) {
85
86
  const inputSet = new Set(json.targetDefaults.lint.inputs);
86
- inputSet.add('{workspaceRoot}/eslint.config.cjs');
87
+ inputSet.add(`{workspaceRoot}/eslint.config.${format}`);
87
88
  json.targetDefaults.lint.inputs = Array.from(inputSet);
88
89
  }
89
90
  if (json.targetDefaults?.['@nx/eslint:lint']?.inputs) {
90
91
  const inputSet = new Set(json.targetDefaults['@nx/eslint:lint'].inputs);
91
- inputSet.add('{workspaceRoot}/eslint.config.cjs');
92
+ inputSet.add(`{workspaceRoot}/eslint.config.${format}`);
92
93
  json.targetDefaults['@nx/eslint:lint'].inputs = Array.from(inputSet);
93
94
  }
94
95
  if (json.namedInputs?.production) {
95
96
  const inputSet = new Set(json.namedInputs.production);
96
- inputSet.add('!{projectRoot}/eslint.config.cjs');
97
+ inputSet.add(`!{projectRoot}/eslint.config.${format}`);
97
98
  json.namedInputs.production = Array.from(inputSet);
98
99
  }
99
100
  return json;
100
101
  });
101
102
  }
102
103
  }
103
- function convertConfigToFlatConfig(tree, root, source, target, ignorePath) {
104
+ function convertConfigToFlatConfig(tree, root, source, target, format, ignorePath) {
104
105
  const ignorePaths = ignorePath
105
106
  ? [ignorePath, `${root}/.eslintignore`]
106
107
  : [`${root}/.eslintignore`];
107
108
  if (source.endsWith('.json')) {
108
109
  const config = (0, devkit_1.readJson)(tree, `${root}/${source}`);
109
- const conversionResult = (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, config, ignorePaths);
110
+ const conversionResult = (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, config, ignorePaths, format);
110
111
  return processConvertedConfig(tree, root, source, target, conversionResult);
111
112
  }
112
113
  if (source.endsWith('.yaml') || source.endsWith('.yml')) {
@@ -116,7 +117,7 @@ function convertConfigToFlatConfig(tree, root, source, target, ignorePath) {
116
117
  json: true,
117
118
  filename: source,
118
119
  });
119
- const conversionResult = (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, config, ignorePaths);
120
+ const conversionResult = (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, config, ignorePaths, format);
120
121
  return processConvertedConfig(tree, root, source, target, conversionResult);
121
122
  }
122
123
  }
@@ -1,3 +1,5 @@
1
1
  export interface ConvertToFlatConfigGeneratorSchema {
2
2
  skipFormat?: boolean;
3
+ // Internal option
4
+ eslintConfigFormat?: 'mjs' | 'cjs';
3
5
  }
@@ -34,6 +34,7 @@ function postTargetTransformer(target, tree, projectDetails, inferredTargetConfi
34
34
  '{workspaceRoot}/.eslintrc.json',
35
35
  '{workspaceRoot}/.eslintignore',
36
36
  '{workspaceRoot}/eslint.config.cjs',
37
+ '{workspaceRoot}/eslint.config.mjs',
37
38
  ].includes(input));
38
39
  if (inputs.length === 0) {
39
40
  delete target.inputs;
@@ -26,4 +26,4 @@ export declare const javaScriptOverride: {
26
26
  rules: {};
27
27
  };
28
28
  export declare const getGlobalEsLintConfiguration: (unitTestRunner?: string, rootProject?: boolean) => Linter.Config;
29
- export declare const getGlobalFlatEslintConfiguration: (rootProject?: boolean) => string;
29
+ export declare const getGlobalFlatEslintConfiguration: (format: "cjs" | "mjs", rootProject?: boolean) => string;
@@ -78,8 +78,8 @@ const getGlobalEsLintConfiguration = (unitTestRunner, rootProject) => {
78
78
  return config;
79
79
  };
80
80
  exports.getGlobalEsLintConfiguration = getGlobalEsLintConfiguration;
81
- const getGlobalFlatEslintConfiguration = (rootProject) => {
82
- const nodeList = (0, ast_utils_1.createNodeList)(new Map(), []);
81
+ const getGlobalFlatEslintConfiguration = (format, rootProject) => {
82
+ const nodeList = (0, ast_utils_1.createNodeList)(new Map(), [], format);
83
83
  let content = (0, ast_utils_1.stringifyNodeList)(nodeList);
84
84
  content = (0, ast_utils_1.addImportToFlatConfig)(content, 'nx', '@nx/eslint-plugin');
85
85
  content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatPredefinedConfig)('flat/base'), { insertAtTheEnd: false });
@@ -87,7 +87,7 @@ const getGlobalFlatEslintConfiguration = (rootProject) => {
87
87
  content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatPredefinedConfig)('flat/javascript'));
88
88
  content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)({
89
89
  ignores: ['**/dist'],
90
- }));
90
+ }, format));
91
91
  if (!rootProject) {
92
92
  content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)({
93
93
  files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
@@ -107,7 +107,7 @@ const getGlobalFlatEslintConfiguration = (rootProject) => {
107
107
  },
108
108
  ],
109
109
  },
110
- }));
110
+ }, format));
111
111
  }
112
112
  content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)({
113
113
  files: [
@@ -119,7 +119,7 @@ const getGlobalFlatEslintConfiguration = (rootProject) => {
119
119
  '**/*.mjs',
120
120
  ],
121
121
  rules: {},
122
- }));
122
+ }, format));
123
123
  return content;
124
124
  };
125
125
  exports.getGlobalFlatEslintConfiguration = getGlobalFlatEslintConfiguration;
@@ -1,3 +1,3 @@
1
1
  import { GeneratorCallback, ProjectConfiguration, TargetConfiguration, Tree } from '@nx/devkit';
2
- export declare function migrateConfigToMonorepoStyle(projects: ProjectConfiguration[], tree: Tree, unitTestRunner: string, keepExistingVersions?: boolean): GeneratorCallback;
2
+ export declare function migrateConfigToMonorepoStyle(projects: ProjectConfiguration[], tree: Tree, unitTestRunner: string, eslintConfigFormat: 'mjs' | 'cjs', keepExistingVersions?: boolean): GeneratorCallback;
3
3
  export declare function findLintTarget(project: ProjectConfiguration): TargetConfiguration;
@@ -11,9 +11,19 @@ const versions_1 = require("../../utils/versions");
11
11
  const ast_utils_1 = require("../utils/flat-config/ast-utils");
12
12
  const plugin_1 = require("../utils/plugin");
13
13
  const config_file_1 = require("../../utils/config-file");
14
- function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, keepExistingVersions) {
14
+ function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, eslintConfigFormat, keepExistingVersions) {
15
15
  const rootEslintConfig = (0, eslint_file_1.findEslintFile)(tree);
16
16
  let skipCleanup = false;
17
+ if (rootEslintConfig) {
18
+ // We do not want to mix the formats
19
+ const fileExtension = (0, path_1.extname)(rootEslintConfig);
20
+ if (fileExtension === '.mjs' || fileExtension === '.cjs') {
21
+ eslintConfigFormat = fileExtension.slice(1);
22
+ }
23
+ else {
24
+ eslintConfigFormat = (0, eslint_file_1.determineEslintConfigFormat)(tree.read(rootEslintConfig, 'utf-8'));
25
+ }
26
+ }
17
27
  if (rootEslintConfig?.match(/\.base\./) &&
18
28
  !projects.some((p) => p.root === '.')) {
19
29
  // if the migration has been run already, we need to rename the base config
@@ -27,9 +37,9 @@ function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, keepExisti
27
37
  (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
28
38
  '@eslint/js': versions_1.eslintVersion,
29
39
  }, undefined, keepExistingVersions);
30
- tree.write(tree.exists('eslint.config.cjs')
31
- ? 'eslint.base.config.cjs'
32
- : 'eslint.config.cjs', (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)());
40
+ tree.write(tree.exists(`eslint.config.${eslintConfigFormat}`)
41
+ ? `eslint.base.config.${eslintConfigFormat}`
42
+ : `eslint.config.${eslintConfigFormat}`, (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(eslintConfigFormat));
33
43
  }
34
44
  else {
35
45
  const eslintFile = (0, eslint_file_1.findEslintFile)(tree, '.');
@@ -80,7 +90,7 @@ function migrateEslintFile(projectEslintPath, tree) {
80
90
  let config = tree.read(projectEslintPath, 'utf-8');
81
91
  // remove @nx plugin
82
92
  config = (0, ast_utils_1.removePlugin)(config, '@nx', '@nx/eslint-plugin-nx');
83
- // extend eslint.base.config.cjs
93
+ // if base config is cjs, we will need to import it using async import
84
94
  config = (0, ast_utils_1.addImportToFlatConfig)(config, 'baseConfig', `${(0, devkit_1.offsetFromRoot)((0, path_1.dirname)(projectEslintPath))}${baseFile}`);
85
95
  config = (0, ast_utils_1.addBlockToFlatConfigExport)(config, (0, ast_utils_1.generateSpreadElement)('baseConfig'), { insertAtTheEnd: false });
86
96
  // cleanup file extends
@@ -4,6 +4,7 @@ export interface LinterInitOptions {
4
4
  keepExistingVersions?: boolean;
5
5
  updatePackageScripts?: boolean;
6
6
  addPlugin?: boolean;
7
+ eslintConfigFormat?: 'mjs' | 'cjs';
7
8
  }
8
9
  export declare function initEsLint(tree: Tree, options: LinterInitOptions): Promise<GeneratorCallback>;
9
10
  export declare function lintInitGenerator(tree: Tree, options: LinterInitOptions): Promise<GeneratorCallback>;
@@ -8,18 +8,19 @@ const versions_1 = require("../../utils/versions");
8
8
  const eslint_file_1 = require("../utils/eslint-file");
9
9
  const plugin_1 = require("../../plugins/plugin");
10
10
  const plugin_2 = require("../utils/plugin");
11
- function updateProductionFileset(tree) {
11
+ const path_1 = require("path");
12
+ function updateProductionFileset(tree, format = 'mjs') {
12
13
  const nxJson = (0, devkit_1.readNxJson)(tree);
13
14
  const productionFileSet = nxJson.namedInputs?.production;
14
15
  if (productionFileSet) {
15
16
  productionFileSet.push('!{projectRoot}/.eslintrc.json');
16
- productionFileSet.push('!{projectRoot}/eslint.config.cjs');
17
+ productionFileSet.push(`!{projectRoot}/eslint.config.${format}`);
17
18
  // Dedupe and set
18
19
  nxJson.namedInputs.production = Array.from(new Set(productionFileSet));
19
20
  }
20
21
  (0, devkit_1.updateNxJson)(tree, nxJson);
21
22
  }
22
- function addTargetDefaults(tree) {
23
+ function addTargetDefaults(tree, format) {
23
24
  const nxJson = (0, devkit_1.readNxJson)(tree);
24
25
  nxJson.targetDefaults ??= {};
25
26
  nxJson.targetDefaults['@nx/eslint:lint'] ??= {};
@@ -28,7 +29,7 @@ function addTargetDefaults(tree) {
28
29
  'default',
29
30
  `{workspaceRoot}/.eslintrc.json`,
30
31
  `{workspaceRoot}/.eslintignore`,
31
- `{workspaceRoot}/eslint.config.cjs`,
32
+ `{workspaceRoot}/eslint.config.${format}`,
32
33
  ];
33
34
  (0, devkit_1.updateNxJson)(tree, nxJson);
34
35
  }
@@ -50,8 +51,18 @@ async function initEsLint(tree, options) {
50
51
  const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
51
52
  nxJson.useInferencePlugins !== false;
52
53
  options.addPlugin ??= addPluginDefault;
54
+ options.eslintConfigFormat ??= 'mjs';
53
55
  const hasPlugin = (0, plugin_2.hasEslintPlugin)(tree);
54
56
  const rootEslintFile = (0, eslint_file_1.findEslintFile)(tree);
57
+ if (rootEslintFile) {
58
+ const fileExtension = (0, path_1.extname)(rootEslintFile);
59
+ if (fileExtension === '.mjs' || fileExtension === '.cjs') {
60
+ options.eslintConfigFormat = fileExtension.slice(1);
61
+ }
62
+ else {
63
+ options.eslintConfigFormat = (0, eslint_file_1.determineEslintConfigFormat)(tree.read(rootEslintFile, 'utf-8'));
64
+ }
65
+ }
55
66
  const graph = await (0, devkit_1.createProjectGraphAsync)();
56
67
  const lintTargetNames = [
57
68
  'lint',
@@ -70,7 +81,7 @@ async function initEsLint(tree, options) {
70
81
  if (rootEslintFile) {
71
82
  return () => { };
72
83
  }
73
- updateProductionFileset(tree);
84
+ updateProductionFileset(tree, options.eslintConfigFormat);
74
85
  updateVsCodeRecommendedExtensions(tree);
75
86
  if (options.addPlugin) {
76
87
  await (0, add_plugin_1.addPlugin)(tree, graph, '@nx/eslint/plugin', plugin_1.createNodesV2, {
@@ -78,7 +89,7 @@ async function initEsLint(tree, options) {
78
89
  }, options.updatePackageScripts);
79
90
  }
80
91
  else {
81
- addTargetDefaults(tree);
92
+ addTargetDefaults(tree, options.eslintConfigFormat);
82
93
  }
83
94
  const tasks = [];
84
95
  if (!options.skipPackageJson) {
@@ -12,6 +12,7 @@ interface LintProjectOptions {
12
12
  rootProject?: boolean;
13
13
  keepExistingVersions?: boolean;
14
14
  addPlugin?: boolean;
15
+ eslintConfigFormat?: 'mjs' | 'cjs';
15
16
  /**
16
17
  * @internal
17
18
  */
@@ -13,11 +13,13 @@ const ast_utils_1 = require("../utils/flat-config/ast-utils");
13
13
  const config_file_1 = require("../../utils/config-file");
14
14
  const plugin_1 = require("../utils/plugin");
15
15
  const setup_root_eslint_1 = require("./setup-root-eslint");
16
+ const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
16
17
  function lintProjectGenerator(tree, options) {
17
18
  return lintProjectGeneratorInternal(tree, { addPlugin: false, ...options });
18
19
  }
19
20
  async function lintProjectGeneratorInternal(tree, options) {
20
21
  const nxJson = (0, devkit_1.readNxJson)(tree);
22
+ options.eslintConfigFormat ??= 'mjs';
21
23
  const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
22
24
  nxJson.useInferencePlugins !== false;
23
25
  options.addPlugin ??= addPluginDefault;
@@ -25,12 +27,14 @@ async function lintProjectGeneratorInternal(tree, options) {
25
27
  const initTask = await (0, init_1.lintInitGenerator)(tree, {
26
28
  skipPackageJson: options.skipPackageJson,
27
29
  addPlugin: options.addPlugin,
30
+ eslintConfigFormat: options.eslintConfigFormat,
28
31
  });
29
32
  tasks.push(initTask);
30
33
  const rootEsLintTask = (0, setup_root_eslint_1.setupRootEsLint)(tree, {
31
34
  unitTestRunner: options.unitTestRunner,
32
35
  skipPackageJson: options.skipPackageJson,
33
36
  rootProject: options.rootProject,
37
+ eslintConfigFormat: options.eslintConfigFormat,
34
38
  });
35
39
  tasks.push(rootEsLintTask);
36
40
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
@@ -41,7 +45,7 @@ async function lintProjectGeneratorInternal(tree, options) {
41
45
  if (lintFilePatterns &&
42
46
  lintFilePatterns.length &&
43
47
  !lintFilePatterns.includes('{projectRoot}') &&
44
- isBuildableLibraryProject(projectConfig)) {
48
+ isBuildableLibraryProject(tree, projectConfig)) {
45
49
  lintFilePatterns.push(`{projectRoot}/package.json`);
46
50
  }
47
51
  const hasPlugin = (0, plugin_1.hasEslintPlugin)(tree);
@@ -84,7 +88,7 @@ async function lintProjectGeneratorInternal(tree, options) {
84
88
  filteredProjects.push(project);
85
89
  }
86
90
  });
87
- const migrateTask = (0, init_migration_1.migrateConfigToMonorepoStyle)(filteredProjects, tree, options.unitTestRunner, options.keepExistingVersions);
91
+ const migrateTask = (0, init_migration_1.migrateConfigToMonorepoStyle)(filteredProjects, tree, options.unitTestRunner, options.eslintConfigFormat, options.keepExistingVersions);
88
92
  tasks.push(migrateTask);
89
93
  }
90
94
  }
@@ -95,7 +99,7 @@ async function lintProjectGeneratorInternal(tree, options) {
95
99
  createEsLintConfiguration(tree, options, projectConfig, options.setParserOptionsProject, options.rootProject);
96
100
  }
97
101
  // Buildable libs need source analysis enabled for linting `package.json`.
98
- if (isBuildableLibraryProject(projectConfig) &&
102
+ if (isBuildableLibraryProject(tree, projectConfig) &&
99
103
  !isJsAnalyzeSourceFilesEnabled(tree)) {
100
104
  (0, devkit_1.updateJson)(tree, 'nx.json', (json) => {
101
105
  json.pluginsConfig ??= {};
@@ -116,8 +120,20 @@ function createEsLintConfiguration(tree, options, projectConfig, setParserOption
116
120
  const pathToRootConfig = extendedRootConfig
117
121
  ? `${(0, devkit_1.offsetFromRoot)(projectConfig.root)}${extendedRootConfig}`
118
122
  : undefined;
123
+ if (extendedRootConfig) {
124
+ // We do not want to mix the formats
125
+ // if the base file extension is `.mjs` we should use `mjs` for the new file
126
+ // or if base the file extension is `.cjs` then the format should be `cjs`
127
+ const fileExtension = (0, path_1.extname)(extendedRootConfig);
128
+ if (fileExtension === '.mjs' || fileExtension === '.cjs') {
129
+ options.eslintConfigFormat = fileExtension.slice(1);
130
+ }
131
+ else {
132
+ options.eslintConfigFormat = (0, eslint_file_1.determineEslintConfigFormat)(tree.read(extendedRootConfig, 'utf-8'));
133
+ }
134
+ }
119
135
  const addDependencyChecks = options.addPackageJsonDependencyChecks ||
120
- isBuildableLibraryProject(projectConfig);
136
+ isBuildableLibraryProject(tree, projectConfig);
121
137
  const overrides = (0, flat_config_1.useFlatConfig)(tree)
122
138
  ? // For flat configs, we don't need to generate different overrides for each file. Users should add their own overrides as needed.
123
139
  []
@@ -180,11 +196,11 @@ function createEsLintConfiguration(tree, options, projectConfig, setParserOption
180
196
  nodes.push((0, ast_utils_1.generateSpreadElement)('baseConfig'));
181
197
  }
182
198
  overrides.forEach((override) => {
183
- nodes.push((0, ast_utils_1.generateFlatOverride)(override));
199
+ nodes.push((0, ast_utils_1.generateFlatOverride)(override, options.eslintConfigFormat));
184
200
  });
185
- const nodeList = (0, ast_utils_1.createNodeList)(importMap, nodes);
201
+ const nodeList = (0, ast_utils_1.createNodeList)(importMap, nodes, options.eslintConfigFormat);
186
202
  const content = (0, ast_utils_1.stringifyNodeList)(nodeList);
187
- tree.write((0, path_1.join)(projectConfig.root, `eslint.config.cjs`), content);
203
+ tree.write((0, path_1.join)(projectConfig.root, `eslint.config.${options.eslintConfigFormat}`), content);
188
204
  }
189
205
  else {
190
206
  (0, devkit_1.writeJson)(tree, (0, path_1.join)(projectConfig.root, `.eslintrc.json`), {
@@ -201,8 +217,9 @@ function isJsAnalyzeSourceFilesEnabled(tree) {
201
217
  return (jsPluginConfig?.analyzeSourceFiles ??
202
218
  nxJson.extends !== 'nx/presets/npm.json');
203
219
  }
204
- function isBuildableLibraryProject(projectConfig) {
205
- return (projectConfig.projectType === 'library' &&
220
+ function isBuildableLibraryProject(tree, projectConfig) {
221
+ return ((0, ts_solution_setup_1.getProjectType)(tree, projectConfig.root, projectConfig.projectType) ===
222
+ 'library' &&
206
223
  projectConfig.targets?.build &&
207
224
  !!projectConfig.targets.build);
208
225
  }
@@ -212,8 +229,7 @@ function isBuildableLibraryProject(projectConfig) {
212
229
  */
213
230
  function isMigrationToMonorepoNeeded(tree, graph) {
214
231
  // the base config is already created, migration has been done
215
- if (tree.exists(config_file_1.baseEsLintConfigFile) ||
216
- tree.exists(config_file_1.baseEsLintFlatConfigFile)) {
232
+ if ([config_file_1.baseEsLintConfigFile, ...config_file_1.BASE_ESLINT_CONFIG_FILENAMES].some((f) => tree.exists(f))) {
217
233
  return false;
218
234
  }
219
235
  const nodes = Object.values(graph.nodes);
@@ -3,5 +3,6 @@ export type SetupRootEsLintOptions = {
3
3
  unitTestRunner?: string;
4
4
  skipPackageJson?: boolean;
5
5
  rootProject?: boolean;
6
+ eslintConfigFormat?: 'mjs' | 'cjs';
6
7
  };
7
8
  export declare function setupRootEsLint(tree: Tree, options: SetupRootEsLintOptions): GeneratorCallback;
@@ -11,6 +11,7 @@ function setupRootEsLint(tree, options) {
11
11
  if (rootEslintFile) {
12
12
  return () => { };
13
13
  }
14
+ options.eslintConfigFormat ??= 'mjs';
14
15
  if (!(0, flat_config_1.useFlatConfig)(tree)) {
15
16
  return setUpLegacyRootEslintRc(tree, options);
16
17
  }
@@ -38,7 +39,7 @@ function setUpLegacyRootEslintRc(tree, options) {
38
39
  : () => { };
39
40
  }
40
41
  function setUpRootFlatConfig(tree, options) {
41
- tree.write('eslint.config.cjs', (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(options.rootProject));
42
+ tree.write(`eslint.config.${options.eslintConfigFormat}`, (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(options.eslintConfigFormat, options.rootProject));
42
43
  return !options.skipPackageJson
43
44
  ? (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
44
45
  '@eslint/js': versions_1.eslint9__eslintVersion,
@@ -3,6 +3,7 @@ import type { Linter } from 'eslint';
3
3
  export declare function findEslintFile(tree: Tree, projectRoot?: string): string | null;
4
4
  export declare function isEslintConfigSupported(tree: Tree, projectRoot?: string): boolean;
5
5
  export declare function updateRelativePathsInConfig(tree: Tree, sourcePath: string, destinationPath: string): void;
6
+ export declare function determineEslintConfigFormat(content: string): 'mjs' | 'cjs';
6
7
  export declare function addOverrideToLintConfig(tree: Tree, root: string, override: Partial<Linter.ConfigOverride<Linter.RulesRecord>>, options?: {
7
8
  insertAtTheEnd?: boolean;
8
9
  checkBaseConfig?: boolean;