@nx/eslint 20.5.0-canary.20250213-b8ee838 → 20.5.0-canary.20250214-ef08108

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.5.0-canary.20250213-b8ee838",
3
+ "version": "20.5.0-canary.20250214-ef08108",
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.5.0-canary.20250213-b8ee838",
39
- "@nx/js": "20.5.0-canary.20250213-b8ee838",
38
+ "@nx/devkit": "20.5.0-canary.20250214-ef08108",
39
+ "@nx/js": "20.5.0-canary.20250214-ef08108",
40
40
  "semver": "^7.5.3",
41
41
  "tslib": "^2.3.0",
42
42
  "typescript": "~5.7.2"
@@ -430,13 +430,26 @@ function addIgnoresToLintConfig(tree, root, ignorePatterns) {
430
430
  break;
431
431
  }
432
432
  }
433
- const block = (0, ast_utils_1.generateAst)({
434
- ignores: ignorePatterns.map((path) => (0, path_utils_1.mapFilePath)(path)),
435
- });
436
- tree.write(fileName, (0, ast_utils_1.addBlockToFlatConfigExport)(tree.read(fileName, 'utf8'), block));
433
+ if (!fileName) {
434
+ return;
435
+ }
436
+ let content = tree.read(fileName, 'utf8');
437
+ if ((0, ast_utils_1.hasFlatConfigIgnoresBlock)(content)) {
438
+ content = (0, ast_utils_1.addPatternsToFlatConfigIgnoresBlock)(content, ignorePatterns);
439
+ tree.write(fileName, content);
440
+ }
441
+ else {
442
+ const block = (0, ast_utils_1.generateAst)({
443
+ ignores: ignorePatterns.map((path) => (0, path_utils_1.mapFilePath)(path)),
444
+ });
445
+ tree.write(fileName, (0, ast_utils_1.addBlockToFlatConfigExport)(content, block));
446
+ }
437
447
  }
438
448
  else {
439
449
  const fileName = (0, devkit_1.joinPathFragments)(root, '.eslintrc.json');
450
+ if (!tree.exists(fileName)) {
451
+ return;
452
+ }
440
453
  (0, devkit_1.updateJson)(tree, fileName, (json) => {
441
454
  const ignoreSet = new Set([
442
455
  ...(json.ignorePatterns ?? []),
@@ -4,6 +4,8 @@ import * as ts from 'typescript';
4
4
  * Remove all overrides from the config file
5
5
  */
6
6
  export declare function removeOverridesFromLintConfig(content: string): string;
7
+ export declare function addPatternsToFlatConfigIgnoresBlock(content: string, ignorePatterns: string[]): string;
8
+ export declare function hasFlatConfigIgnoresBlock(content: string): boolean;
7
9
  export declare function hasOverride(content: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean): boolean;
8
10
  /**
9
11
  * Finds an override matching the lookup function and applies the update function to it
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.removeOverridesFromLintConfig = removeOverridesFromLintConfig;
4
+ exports.addPatternsToFlatConfigIgnoresBlock = addPatternsToFlatConfigIgnoresBlock;
5
+ exports.hasFlatConfigIgnoresBlock = hasFlatConfigIgnoresBlock;
4
6
  exports.hasOverride = hasOverride;
5
7
  exports.replaceOverride = replaceOverride;
6
8
  exports.addImportToFlatConfig = addImportToFlatConfig;
@@ -73,6 +75,55 @@ function findModuleExports(source) {
73
75
  }
74
76
  });
75
77
  }
78
+ function addPatternsToFlatConfigIgnoresBlock(content, ignorePatterns) {
79
+ const source = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
80
+ const format = content.includes('export default') ? 'mjs' : 'cjs';
81
+ const exportsArray = format === 'mjs' ? findExportDefault(source) : findModuleExports(source);
82
+ if (!exportsArray) {
83
+ return content;
84
+ }
85
+ const changes = [];
86
+ for (const node of exportsArray) {
87
+ if (!isFlatConfigIgnoresBlock(node)) {
88
+ continue;
89
+ }
90
+ const start = node.properties.pos + 1; // keep leading line break
91
+ const data = parseTextToJson(node.getFullText());
92
+ changes.push({
93
+ type: devkit_1.ChangeType.Delete,
94
+ start,
95
+ length: node.properties.end - start,
96
+ });
97
+ data.ignores = Array.from(new Set([...(data.ignores ?? []), ...ignorePatterns]));
98
+ changes.push({
99
+ type: devkit_1.ChangeType.Insert,
100
+ index: start,
101
+ text: ' ' +
102
+ JSON.stringify(data, null, 2)
103
+ .slice(2, -2) // Remove curly braces and start/end line breaks
104
+ .replaceAll(/\n/g, '\n '), // Maintain indentation
105
+ });
106
+ break;
107
+ }
108
+ return (0, devkit_1.applyChangesToString)(content, changes);
109
+ }
110
+ function hasFlatConfigIgnoresBlock(content) {
111
+ const source = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
112
+ const format = content.includes('export default') ? 'mjs' : 'cjs';
113
+ const exportsArray = format === 'mjs' ? findExportDefault(source) : findModuleExports(source);
114
+ if (!exportsArray) {
115
+ return false;
116
+ }
117
+ return exportsArray.some(isFlatConfigIgnoresBlock);
118
+ }
119
+ function isFlatConfigIgnoresBlock(node) {
120
+ return (ts.isObjectLiteralExpression(node) &&
121
+ node.properties.length === 1 &&
122
+ (node.properties[0].name.getText() === 'ignores' ||
123
+ node.properties[0].name.getText() === '"ignores"') &&
124
+ ts.isPropertyAssignment(node.properties[0]) &&
125
+ ts.isArrayLiteralExpression(node.properties[0].initializer));
126
+ }
76
127
  function isOverride(node) {
77
128
  return ((ts.isObjectLiteralExpression(node) &&
78
129
  node.properties.some((p) => p.name.getText() === 'files' || p.name.getText() === '"files"')) ||
@@ -107,7 +107,7 @@ const internalCreateNodes = async (configFilePath, options, context, projectsCac
107
107
  projects,
108
108
  };
109
109
  };
110
- const internalCreateNodesV2 = async (configFilePath, options, context, eslintConfigFiles, projectRootsByEslintRoots, lintableFilesPerProjectRoot, projectsCache) => {
110
+ const internalCreateNodesV2 = async (configFilePath, options, context, projectRootsByEslintRoots, lintableFilesPerProjectRoot, projectsCache, hashByRoot) => {
111
111
  const configDir = (0, posix_1.dirname)(configFilePath);
112
112
  const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)({
113
113
  useFlatConfigOverrideVal: (0, config_file_1.isFlatConfig)(configFilePath),
@@ -115,12 +115,7 @@ const internalCreateNodesV2 = async (configFilePath, options, context, eslintCon
115
115
  const eslintVersion = ESLint.version;
116
116
  const projects = {};
117
117
  await Promise.all(projectRootsByEslintRoots.get(configDir).map(async (projectRoot) => {
118
- const parentConfigs = eslintConfigFiles.filter((eslintConfig) => isSubDir(projectRoot, (0, posix_1.dirname)(eslintConfig)));
119
- const hash = await (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options, {
120
- configFiles: eslintConfigFiles,
121
- nxJsonConfiguration: context.nxJsonConfiguration,
122
- workspaceRoot: context.workspaceRoot,
123
- }, [...parentConfigs, (0, posix_1.join)(projectRoot, '.eslintignore')]);
118
+ const hash = hashByRoot.get(projectRoot);
124
119
  if (projectsCache[hash]) {
125
120
  // We can reuse the projects in the cache.
126
121
  Object.assign(projects, projectsCache[hash]);
@@ -165,8 +160,13 @@ exports.createNodesV2 = [
165
160
  const targetsCache = readTargetsCache(cachePath);
166
161
  const { eslintConfigFiles, projectRoots, projectRootsByEslintRoots } = splitConfigFiles(configFiles);
167
162
  const lintableFilesPerProjectRoot = await collectLintableFilesByProjectRoot(projectRoots, options, context);
163
+ const hashes = await (0, calculate_hash_for_create_nodes_1.calculateHashesForCreateNodes)(projectRoots, options, context, projectRoots.map((root) => {
164
+ const parentConfigs = eslintConfigFiles.filter((eslintConfig) => isSubDir(root, (0, posix_1.dirname)(eslintConfig)));
165
+ return [...parentConfigs, (0, posix_1.join)(root, '.eslintignore')];
166
+ }));
167
+ const hashByRoot = new Map(projectRoots.map((r, i) => [r, hashes[i]]));
168
168
  try {
169
- return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) => internalCreateNodesV2(configFile, options, context, eslintConfigFiles, projectRootsByEslintRoots, lintableFilesPerProjectRoot, targetsCache), eslintConfigFiles, options, context);
169
+ return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) => internalCreateNodesV2(configFile, options, context, projectRootsByEslintRoots, lintableFilesPerProjectRoot, targetsCache, hashByRoot), eslintConfigFiles, options, context);
170
170
  }
171
171
  finally {
172
172
  writeTargetsToCache(cachePath, targetsCache);