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

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/migrations.json +40 -0
  2. package/package.json +4 -4
  3. package/src/generators/convert-to-flat-config/converters/json-converter.d.ts +1 -1
  4. package/src/generators/convert-to-flat-config/converters/json-converter.js +6 -6
  5. package/src/generators/convert-to-flat-config/generator.js +17 -16
  6. package/src/generators/convert-to-flat-config/schema.d.ts +2 -0
  7. package/src/generators/convert-to-inferred/convert-to-inferred.js +1 -0
  8. package/src/generators/init/global-eslint-config.d.ts +1 -1
  9. package/src/generators/init/global-eslint-config.js +5 -5
  10. package/src/generators/init/init-migration.d.ts +1 -1
  11. package/src/generators/init/init-migration.js +15 -5
  12. package/src/generators/init/init.d.ts +1 -0
  13. package/src/generators/init/init.js +17 -6
  14. package/src/generators/lint-project/lint-project.d.ts +1 -0
  15. package/src/generators/lint-project/lint-project.js +27 -11
  16. package/src/generators/lint-project/setup-root-eslint.d.ts +1 -0
  17. package/src/generators/lint-project/setup-root-eslint.js +2 -1
  18. package/src/generators/utils/eslint-file.d.ts +1 -0
  19. package/src/generators/utils/eslint-file.js +54 -14
  20. package/src/generators/utils/flat-config/ast-utils.d.ts +10 -4
  21. package/src/generators/utils/flat-config/ast-utils.js +328 -59
  22. package/src/generators/workspace-rules-project/workspace-rules-project.js +2 -1
  23. package/src/plugins/plugin.js +1 -1
  24. package/src/utils/config-file.d.ts +2 -1
  25. package/src/utils/config-file.js +3 -2
  26. package/src/utils/flat-config.d.ts +1 -0
  27. package/src/utils/flat-config.js +8 -2
  28. package/src/utils/versions.d.ts +1 -1
  29. package/src/utils/versions.js +1 -1
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findEslintFile = findEslintFile;
4
4
  exports.isEslintConfigSupported = isEslintConfigSupported;
5
5
  exports.updateRelativePathsInConfig = updateRelativePathsInConfig;
6
+ exports.determineEslintConfigFormat = determineEslintConfigFormat;
6
7
  exports.addOverrideToLintConfig = addOverrideToLintConfig;
7
8
  exports.updateOverrideInLintConfig = updateOverrideInLintConfig;
8
9
  exports.lintConfigHasOverride = lintConfigHasOverride;
@@ -20,17 +21,18 @@ const version_utils_1 = require("../../utils/version-utils");
20
21
  const versions_1 = require("../../utils/versions");
21
22
  const ast_utils_1 = require("./flat-config/ast-utils");
22
23
  const path_utils_1 = require("./flat-config/path-utils");
24
+ const ts = require("typescript");
23
25
  const posix_1 = require("node:path/posix");
24
26
  function findEslintFile(tree, projectRoot) {
25
- if (projectRoot === undefined && tree.exists(config_file_1.baseEsLintConfigFile)) {
26
- return config_file_1.baseEsLintConfigFile;
27
- }
28
- if (projectRoot === undefined && tree.exists(config_file_1.baseEsLintFlatConfigFile)) {
29
- return config_file_1.baseEsLintFlatConfigFile;
30
- }
31
- if (projectRoot === undefined &&
32
- tree.exists(config_file_1.legacyBaseEsLintFlatConfigFile)) {
33
- return config_file_1.legacyBaseEsLintFlatConfigFile;
27
+ if (projectRoot === undefined) {
28
+ for (const file of [
29
+ config_file_1.baseEsLintConfigFile,
30
+ ...config_file_1.BASE_ESLINT_CONFIG_FILENAMES,
31
+ ]) {
32
+ if (tree.exists(file)) {
33
+ return file;
34
+ }
35
+ }
34
36
  }
35
37
  projectRoot ??= '';
36
38
  for (const file of config_file_1.ESLINT_CONFIG_FILENAMES) {
@@ -47,7 +49,8 @@ function isEslintConfigSupported(tree, projectRoot = '') {
47
49
  }
48
50
  return (eslintFile.endsWith('.json') ||
49
51
  eslintFile.endsWith('.config.js') ||
50
- eslintFile.endsWith('.config.cjs'));
52
+ eslintFile.endsWith('.config.cjs') ||
53
+ eslintFile.endsWith('.config.mjs'));
51
54
  }
52
55
  function updateRelativePathsInConfig(tree, sourcePath, destinationPath) {
53
56
  if (sourcePath === destinationPath ||
@@ -91,6 +94,17 @@ function replaceFlatConfigPaths(config, sourceRoot, offset, destinationRoot, tre
91
94
  `require('${newPath}')` +
92
95
  newConfig.slice(match.index + match[0].length);
93
96
  }
97
+ // Handle import statements
98
+ const importRegex = RegExp(/import\s+.*?\s+from\s+['"](.*)['"]/g);
99
+ while ((match = importRegex.exec(newConfig)) !== null) {
100
+ const oldPath = match[1];
101
+ const newPath = offsetFilePath(sourceRoot, oldPath, offset, tree);
102
+ // Replace the old path with the updated path
103
+ newConfig =
104
+ newConfig.slice(0, match.index + match[0].indexOf(oldPath)) +
105
+ newPath +
106
+ newConfig.slice(match.index + match[0].indexOf(oldPath) + oldPath.length);
107
+ }
94
108
  // replace projects
95
109
  const projectRegex = RegExp(/project:\s?\[?['"](.*)['"]\]?/g);
96
110
  while ((match = projectRegex.exec(newConfig)) !== null) {
@@ -116,6 +130,12 @@ function offsetFilePath(projectRoot, pathToFile, offset, tree) {
116
130
  }
117
131
  return (0, devkit_1.joinPathFragments)(offset, projectRoot, pathToFile);
118
132
  }
133
+ function determineEslintConfigFormat(content) {
134
+ const sourceFile = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true);
135
+ // Check if there's an `export default` in the AST
136
+ const hasExportDefault = sourceFile.statements.some((statement) => ts.isExportAssignment(statement) && !statement.isExportEquals);
137
+ return hasExportDefault ? 'mjs' : 'cjs';
138
+ }
119
139
  function addOverrideToLintConfig(tree, root, override, options = {
120
140
  insertAtTheEnd: true,
121
141
  }) {
@@ -123,7 +143,12 @@ function addOverrideToLintConfig(tree, root, override, options = {
123
143
  if ((0, flat_config_1.useFlatConfig)(tree)) {
124
144
  let fileName;
125
145
  if (isBase) {
126
- fileName = (0, devkit_1.joinPathFragments)(root, config_file_1.baseEsLintFlatConfigFile);
146
+ for (const file of config_file_1.BASE_ESLINT_CONFIG_FILENAMES) {
147
+ if (tree.exists((0, devkit_1.joinPathFragments)(root, file))) {
148
+ fileName = (0, devkit_1.joinPathFragments)(root, file);
149
+ break;
150
+ }
151
+ }
127
152
  }
128
153
  else {
129
154
  for (const f of flat_config_1.eslintFlatConfigFilenames) {
@@ -133,8 +158,9 @@ function addOverrideToLintConfig(tree, root, override, options = {
133
158
  }
134
159
  }
135
160
  }
136
- const flatOverride = (0, ast_utils_1.generateFlatOverride)(override);
137
161
  let content = tree.read(fileName, 'utf8');
162
+ const format = content.includes('export default') ? 'mjs' : 'cjs';
163
+ const flatOverride = (0, ast_utils_1.generateFlatOverride)(override, format);
138
164
  // Check if the provided override using legacy eslintrc properties or plugins, if so we need to add compat
139
165
  if ((0, ast_utils_1.overrideNeedsCompat)(override)) {
140
166
  content = (0, ast_utils_1.addFlatCompatToFlatConfig)(content);
@@ -213,7 +239,12 @@ function lintConfigHasOverride(tree, rootOrFile, lookup, checkBaseConfig = false
213
239
  checkBaseConfig &&
214
240
  findEslintFile(tree, root).includes('.base');
215
241
  if (isBase) {
216
- fileName = (0, devkit_1.joinPathFragments)(root, config_file_1.baseEsLintFlatConfigFile);
242
+ for (const file of config_file_1.BASE_ESLINT_CONFIG_FILENAMES) {
243
+ if (tree.exists((0, devkit_1.joinPathFragments)(root, file))) {
244
+ fileName = (0, devkit_1.joinPathFragments)(root, file);
245
+ break;
246
+ }
247
+ }
217
248
  }
218
249
  if ((0, flat_config_1.useFlatConfig)(tree)) {
219
250
  if (!fileName) {
@@ -242,13 +273,14 @@ function replaceOverridesInLintConfig(tree, root, overrides) {
242
273
  }
243
274
  }
244
275
  let content = tree.read(fileName, 'utf8');
276
+ const format = content.includes('export default') ? 'mjs' : 'cjs';
245
277
  // Check if any of the provided overrides using legacy eslintrc properties or plugins, if so we need to add compat
246
278
  if (overrides.some(ast_utils_1.overrideNeedsCompat)) {
247
279
  content = (0, ast_utils_1.addFlatCompatToFlatConfig)(content);
248
280
  }
249
281
  content = (0, ast_utils_1.removeOverridesFromLintConfig)(content);
250
282
  overrides.forEach((override) => {
251
- const flatOverride = (0, ast_utils_1.generateFlatOverride)(override);
283
+ const flatOverride = (0, ast_utils_1.generateFlatOverride)(override, format);
252
284
  content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, flatOverride);
253
285
  });
254
286
  tree.write(fileName, content);
@@ -271,6 +303,14 @@ function addExtendsToLintConfig(tree, root, plugin, insertAtTheEnd = false) {
271
303
  break;
272
304
  }
273
305
  }
306
+ // Check the file extension to determine the format of the config if it is .js we look for the export
307
+ const eslintConfigFormat = fileName.endsWith('.mjs')
308
+ ? 'mjs'
309
+ : fileName.endsWith('.cjs')
310
+ ? 'cjs'
311
+ : tree.read(fileName, 'utf-8').includes('module.exports')
312
+ ? 'cjs'
313
+ : 'mjs';
274
314
  let shouldImportEslintCompat = false;
275
315
  // assume eslint version is 9 if not found, as it's what we'd be generating by default
276
316
  const eslintVersion = (0, version_utils_1.getInstalledEslintVersion)(tree) ?? versions_1.eslint9__eslintVersion;
@@ -10,7 +10,12 @@ export declare function hasOverride(content: string, lookup: (override: Linter.C
10
10
  */
11
11
  export declare function replaceOverride(content: string, root: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean, update?: (override: Partial<Linter.ConfigOverride<Linter.RulesRecord>>) => Partial<Linter.ConfigOverride<Linter.RulesRecord>>): string;
12
12
  /**
13
- * Adding require statement to the top of the file
13
+ * Adding import statement to the top of the file
14
+ * The imports are added based on a few rules:
15
+ * 1. If it's a default import and matches the variable, return content unchanged.
16
+ * 2. If it's a named import and the variables are not part of the import object, add them.
17
+ * 3. If no existing import and variable is a string, add a default import.
18
+ * 4. If no existing import and variable is an array, add it as an object import.
14
19
  */
15
20
  export declare function addImportToFlatConfig(content: string, variable: string | string[], imp: string): string;
16
21
  /**
@@ -18,7 +23,7 @@ export declare function addImportToFlatConfig(content: string, variable: string
18
23
  */
19
24
  export declare function removeImportFromFlatConfig(content: string, variable: string, imp: string): string;
20
25
  /**
21
- * Injects new ts.expression to the end of the module.exports array.
26
+ * Injects new ts.expression to the end of the module.exports or export default array.
22
27
  */
23
28
  export declare function addBlockToFlatConfigExport(content: string, config: ts.Expression | ts.SpreadElement, options?: {
24
29
  insertAtTheEnd?: boolean;
@@ -43,7 +48,7 @@ export declare function addFlatCompatToFlatConfig(content: string): string;
43
48
  * Generate node list representing the imports and the exports blocks
44
49
  * Optionally add flat compat initialization
45
50
  */
46
- export declare function createNodeList(importsMap: Map<string, string>, exportElements: ts.Expression[]): ts.NodeArray<ts.VariableStatement | ts.Identifier | ts.ExpressionStatement | ts.SourceFile>;
51
+ export declare function createNodeList(importsMap: Map<string, string>, exportElements: ts.Expression[], format: 'mjs' | 'cjs'): ts.NodeArray<ts.VariableStatement | ts.Identifier | ts.ExpressionStatement | ts.SourceFile>;
47
52
  export declare function generateSpreadElement(name: string): ts.SpreadElement;
48
53
  export declare function generatePluginExtendsElement(plugins: string[]): ts.SpreadElement;
49
54
  export declare function generatePluginExtendsElementWithCompatFixup(plugin: string): ts.SpreadElement;
@@ -55,6 +60,7 @@ export declare function stringifyNodeList(nodes: ts.NodeArray<ts.VariableStateme
55
60
  * generates AST require statement
56
61
  */
57
62
  export declare function generateRequire(variableName: string | ts.ObjectBindingPattern, imp: string): ts.VariableStatement;
63
+ export declare function generateESMImport(variableName: string | ts.ObjectBindingPattern, imp: string): ts.ImportDeclaration;
58
64
  export declare function overrideNeedsCompat(override: Partial<Linter.ConfigOverride<Linter.RulesRecord>>): string | string[] | {
59
65
  [name: string]: boolean;
60
66
  };
@@ -64,7 +70,7 @@ export declare function overrideNeedsCompat(override: Partial<Linter.ConfigOverr
64
70
  */
65
71
  export declare function generateFlatOverride(_override: Partial<Linter.ConfigOverride<Linter.RulesRecord>> & {
66
72
  ignores?: Linter.FlatConfig['ignores'];
67
- }): ts.ObjectLiteralExpression | ts.SpreadElement;
73
+ }, format: 'mjs' | 'cjs'): ts.ObjectLiteralExpression | ts.SpreadElement;
68
74
  export declare function generateFlatPredefinedConfig(predefinedConfigName: string, moduleName?: string, spread?: boolean): ts.ObjectLiteralExpression | ts.SpreadElement | ts.ElementAccessExpression;
69
75
  export declare function mapFilePaths<T extends Partial<Linter.ConfigOverride<Linter.RulesRecord>>>(_override: T): T;
70
76
  /**