@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.
@@ -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
  /**