@nx/eslint 17.1.0-beta.0 → 17.1.0-beta.3

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.
package/migrations.json CHANGED
@@ -27,6 +27,11 @@
27
27
  "version": "17.0.0-beta.7",
28
28
  "description": "update-17-0-0-rename-to-eslint",
29
29
  "implementation": "./src/migrations/update-17-0-0-rename-to-eslint/update-17-0-0-rename-to-eslint"
30
+ },
31
+ "update-typescript-eslint": {
32
+ "version": "17.1.0-beta.1",
33
+ "description": "Updates for @typescript-utils/utils v6.9.1+",
34
+ "implementation": "./src/migrations/update-17-1-0/update-typescript-eslint"
30
35
  }
31
36
  },
32
37
  "packageJsonUpdates": {
@@ -82,6 +87,20 @@
82
87
  "version": "^9.0.0"
83
88
  }
84
89
  }
90
+ },
91
+ "17.1.0": {
92
+ "version": "17.1.0-beta.1",
93
+ "packages": {
94
+ "@typescript-eslint/parser": {
95
+ "version": "^6.9.1"
96
+ },
97
+ "@typescript-eslint/eslint-plugin": {
98
+ "version": "^6.9.1"
99
+ },
100
+ "@typescript-eslint/utils": {
101
+ "version": "^6.9.1"
102
+ }
103
+ }
85
104
  }
86
105
  }
87
106
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/eslint",
3
- "version": "17.1.0-beta.0",
3
+ "version": "17.1.0-beta.3",
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": {
@@ -34,10 +34,10 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "tslib": "^2.3.0",
37
- "@nx/devkit": "17.1.0-beta.0",
38
- "@nx/js": "17.1.0-beta.0",
39
- "typescript": "~5.1.3",
40
- "@nx/linter": "17.1.0-beta.0"
37
+ "@nx/devkit": "17.1.0-beta.3",
38
+ "@nx/js": "17.1.0-beta.3",
39
+ "typescript": "~5.2.2",
40
+ "@nx/linter": "17.1.0-beta.3"
41
41
  },
42
42
  "peerDependenciesMeta": {
43
43
  "eslint": {
@@ -27,17 +27,13 @@ async function run(options, context) {
27
27
  options.cacheLocation = options.cacheLocation
28
28
  ? (0, devkit_1.joinPathFragments)(options.cacheLocation, projectName)
29
29
  : undefined;
30
- const { printConfig, ...normalizedOptions } = options;
30
+ const { printConfig, errorOnUnmatchedPattern, ...normalizedOptions } = options;
31
31
  /**
32
32
  * Until ESLint v9 is released and the new so called flat config is the default
33
33
  * we only want to support it if the user has explicitly opted into it by converting
34
34
  * their root ESLint config to use eslint.config.js
35
35
  */
36
36
  const hasFlatConfig = (0, fs_1.existsSync)((0, devkit_1.joinPathFragments)(devkit_1.workspaceRoot, 'eslint.config.js'));
37
- if (!eslintConfigPath && hasFlatConfig) {
38
- const projectRoot = context.projectsConfigurations.projects[context.projectName].root;
39
- eslintConfigPath = (0, devkit_1.joinPathFragments)(projectRoot, 'eslint.config.js');
40
- }
41
37
  const { eslint, ESLint } = await (0, eslint_utils_1.resolveAndInstantiateESLint)(eslintConfigPath, normalizedOptions, hasFlatConfig);
42
38
  const version = ESLint.version?.split('.');
43
39
  if (!version ||
@@ -84,7 +80,7 @@ Please see https://nx.dev/guides/eslint for full guidance on how to resolve this
84
80
  // If some unexpected error, rethrow
85
81
  throw err;
86
82
  }
87
- if (lintResults.length === 0) {
83
+ if (lintResults.length === 0 && errorOnUnmatchedPattern) {
88
84
  const ignoredPatterns = (await Promise.all(normalizedOptions.lintFilePatterns.map(async (pattern) => (await eslint.isPathIgnored(pattern)) ? pattern : null)))
89
85
  .filter((pattern) => !!pattern)
90
86
  .map((pattern) => `- '${pattern}'`);
@@ -21,6 +21,7 @@ export interface Schema extends JsonObject {
21
21
  resolvePluginsRelativeTo: string | null;
22
22
  reportUnusedDisableDirectives: Linter.StringSeverity | null;
23
23
  printConfig?: string | null;
24
+ errorOnUnmatchedPattern?: boolean;
24
25
  }
25
26
 
26
27
  type Formatter =
@@ -137,6 +137,11 @@
137
137
  "type": "string",
138
138
  "description": "The equivalent of the `--print-config` flag on the ESLint CLI.",
139
139
  "x-completion-type": "file"
140
+ },
141
+ "errorOnUnmatchedPattern": {
142
+ "type": "boolean",
143
+ "description": "When set to false, equivalent of the `--no-error-on-unmatched-pattern` flag on the ESLint CLI.",
144
+ "default": true
140
145
  }
141
146
  },
142
147
  "required": ["lintFilePatterns"],
@@ -3,4 +3,4 @@ import { Tree } from '@nx/devkit';
3
3
  * Converts an ESLint JSON config to a flat config.
4
4
  * Deletes the original file along with .eslintignore if it exists.
5
5
  */
6
- export declare function convertEslintJsonToFlatConfig(tree: Tree, root: string, sourceFile: string, destinationFile: string): void;
6
+ export declare function convertEslintJsonToFlatConfig(tree: Tree, root: string, sourceFile: string, destinationFile: string, ignorePaths: string[]): void;
@@ -11,7 +11,7 @@ const eslint_file_1 = require("../../utils/eslint-file");
11
11
  * Converts an ESLint JSON config to a flat config.
12
12
  * Deletes the original file along with .eslintignore if it exists.
13
13
  */
14
- function convertEslintJsonToFlatConfig(tree, root, sourceFile, destinationFile) {
14
+ function convertEslintJsonToFlatConfig(tree, root, sourceFile, destinationFile, ignorePaths) {
15
15
  const importsMap = new Map();
16
16
  const exportElements = [];
17
17
  let isFlatCompatNeeded = false;
@@ -83,18 +83,19 @@ function convertEslintJsonToFlatConfig(tree, root, sourceFile, destinationFile)
83
83
  }));
84
84
  }
85
85
  }
86
- if (tree.exists(`${root}/.eslintignore`)) {
87
- const patterns = tree
88
- .read(`${root}/.eslintignore`, 'utf-8')
89
- .split('\n')
90
- .filter((line) => line.length > 0 && line !== 'node_modules')
91
- .map((path) => (0, ast_utils_1.mapFilePath)(path, root));
92
- if (patterns.length > 0) {
93
- exportElements.push((0, ast_utils_1.generateAst)({ ignores: patterns }));
86
+ for (const ignorePath of ignorePaths) {
87
+ if (tree.exists(ignorePath)) {
88
+ const patterns = tree
89
+ .read(ignorePath, 'utf-8')
90
+ .split('\n')
91
+ .filter((line) => line.length > 0 && line !== 'node_modules')
92
+ .map((path) => (0, ast_utils_1.mapFilePath)(path, root));
93
+ if (patterns.length > 0) {
94
+ exportElements.push((0, ast_utils_1.generateAst)({ ignores: patterns }));
95
+ }
94
96
  }
95
97
  }
96
98
  tree.delete((0, path_1.join)(root, sourceFile));
97
- tree.delete((0, path_1.join)(root, '.eslintignore'));
98
99
  // create the node list and print it to new file
99
100
  const nodeList = (0, ast_utils_1.createNodeList)(importsMap, exportElements, isFlatCompatNeeded);
100
101
  const content = (0, ast_utils_1.stringifyNodeList)(nodeList, root, destinationFile);
@@ -12,12 +12,17 @@ async function convertToFlatConfigGenerator(tree, options) {
12
12
  if (!eslintFile.endsWith('.json')) {
13
13
  throw new Error('Only json eslint config files are supported for conversion');
14
14
  }
15
- // rename root eslint config to eslint.config.js
15
+ const eslintIgnoreFiles = new Set(['.eslintignore']);
16
+ // convert root eslint config to eslint.config.js
16
17
  convertRootToFlatConfig(tree, eslintFile);
17
- // rename and map files
18
+ // convert project eslint files to eslint.config.js
18
19
  const projects = (0, devkit_1.getProjects)(tree);
19
20
  for (const [project, projectConfig] of projects) {
20
- convertProjectToFlatConfig(tree, project, projectConfig, (0, devkit_1.readNxJson)(tree));
21
+ convertProjectToFlatConfig(tree, project, projectConfig, (0, devkit_1.readNxJson)(tree), eslintIgnoreFiles);
22
+ }
23
+ // delete all .eslintignore files
24
+ for (const ignoreFile of eslintIgnoreFiles) {
25
+ tree.delete(ignoreFile);
21
26
  }
22
27
  // replace references in nx.json
23
28
  updateNxJsonConfig(tree);
@@ -34,22 +39,31 @@ function convertRootToFlatConfig(tree, eslintFile) {
34
39
  }
35
40
  convertConfigToFlatConfig(tree, '', '.eslintrc.json', 'eslint.config.js');
36
41
  }
37
- function convertProjectToFlatConfig(tree, project, projectConfig, nxJson) {
42
+ function convertProjectToFlatConfig(tree, project, projectConfig, nxJson, eslintIgnoreFiles) {
38
43
  if (tree.exists(`${projectConfig.root}/.eslintrc.json`)) {
39
44
  if (projectConfig.targets) {
40
45
  const eslintTargets = Object.keys(projectConfig.targets || {}).filter((t) => projectConfig.targets[t].executor === '@nx/eslint:lint');
46
+ let ignorePath;
41
47
  for (const target of eslintTargets) {
42
48
  // remove any obsolete `eslintConfig` options pointing to the old config file
43
49
  if (projectConfig.targets[target].options?.eslintConfig) {
44
50
  delete projectConfig.targets[target].options.eslintConfig;
45
51
  }
52
+ if (projectConfig.targets[target].options?.ignorePath) {
53
+ ignorePath = projectConfig.targets[target].options.ignorePath;
54
+ delete projectConfig.targets[target].options.ignorePath;
55
+ }
46
56
  (0, devkit_1.updateProjectConfiguration)(tree, project, projectConfig);
47
57
  }
48
58
  const nxHasLintTargets = Object.keys(nxJson.targetDefaults || {}).some((t) => (t === '@nx/eslint:lint' ||
49
59
  nxJson.targetDefaults[t].executor === '@nx/eslint:lint') &&
50
60
  projectConfig.targets?.[t]);
51
61
  if (nxHasLintTargets || eslintTargets.length > 0) {
52
- convertConfigToFlatConfig(tree, projectConfig.root, '.eslintrc.json', 'eslint.config.js');
62
+ convertConfigToFlatConfig(tree, projectConfig.root, '.eslintrc.json', 'eslint.config.js', ignorePath);
63
+ eslintIgnoreFiles.add(`${projectConfig.root}/.eslintignore`);
64
+ if (ignorePath) {
65
+ eslintIgnoreFiles.add(ignorePath);
66
+ }
53
67
  }
54
68
  }
55
69
  }
@@ -78,6 +92,9 @@ function updateNxJsonConfig(tree) {
78
92
  });
79
93
  }
80
94
  }
81
- function convertConfigToFlatConfig(tree, root, source, target) {
82
- (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, source, target);
95
+ function convertConfigToFlatConfig(tree, root, source, target, ignorePath) {
96
+ const ignorePaths = ignorePath
97
+ ? [ignorePath, `${root}/.eslintignore`]
98
+ : [`${root}/.eslintignore`];
99
+ (0, json_converter_1.convertEslintJsonToFlatConfig)(tree, root, source, target, ignorePaths);
83
100
  }
@@ -54,7 +54,6 @@ function migrateEslintFile(projectEslintPath, tree) {
54
54
  'plugin:@nrwl/typescript',
55
55
  'plugin:@nrwl/javascript',
56
56
  ]);
57
- console.warn('Flat eslint config is not supported yet for migration');
58
57
  tree.write(projectEslintPath, config);
59
58
  }
60
59
  else {
@@ -223,19 +223,23 @@ function addBlockToFlatConfigExport(content, config, options = {
223
223
  });
224
224
  const insert = printer.printNode(ts.EmitHint.Expression, config, source);
225
225
  if (options.insertAtTheEnd) {
226
+ const index = exportsArray.length > 0
227
+ ? exportsArray.at(exportsArray.length - 1).end
228
+ : exportsArray.pos;
226
229
  return (0, devkit_1.applyChangesToString)(content, [
227
230
  {
228
231
  type: devkit_1.ChangeType.Insert,
229
- index: exportsArray[exportsArray.length - 1].end,
232
+ index,
230
233
  text: `,\n${insert}`,
231
234
  },
232
235
  ]);
233
236
  }
234
237
  else {
238
+ const index = exportsArray.length > 0 ? exportsArray.at(0).pos : exportsArray.pos;
235
239
  return (0, devkit_1.applyChangesToString)(content, [
236
240
  {
237
241
  type: devkit_1.ChangeType.Insert,
238
- index: exportsArray[0].pos,
242
+ index,
239
243
  text: `\n${insert},`,
240
244
  },
241
245
  ]);
@@ -25,7 +25,7 @@ export const rule = ESLintUtils.RuleCreator(() => __filename)({
25
25
  type: 'problem',
26
26
  docs: {
27
27
  description: ``,
28
- recommended: 'error',
28
+ recommended: 'recommended',
29
29
  },
30
30
  schema: [],
31
31
  messages: {},
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "extends": "<%= rootTsConfigPath %>",
3
3
  "compilerOptions": {
4
- "module": "commonjs"
4
+ "moduleResolution": "node16",
5
+ "module": "node16"
5
6
  },
6
7
  "files": [],
7
8
  "include": [],
@@ -1,7 +1,7 @@
1
- import { Tree } from '@nx/devkit';
1
+ import { GeneratorCallback, Tree } from '@nx/devkit';
2
2
  export declare const WORKSPACE_RULES_PROJECT_NAME = "eslint-rules";
3
3
  export declare const WORKSPACE_PLUGIN_DIR = "tools/eslint-rules";
4
4
  export interface LintWorkspaceRulesProjectGeneratorOptions {
5
5
  skipFormat?: boolean;
6
6
  }
7
- export declare function lintWorkspaceRulesProjectGenerator(tree: Tree, options?: LintWorkspaceRulesProjectGeneratorOptions): Promise<import("@nx/devkit").GeneratorCallback>;
7
+ export declare function lintWorkspaceRulesProjectGenerator(tree: Tree, options?: LintWorkspaceRulesProjectGeneratorOptions): Promise<GeneratorCallback>;
@@ -10,7 +10,8 @@ const workspace_lint_rules_1 = require("../../utils/workspace-lint-rules");
10
10
  exports.WORKSPACE_RULES_PROJECT_NAME = 'eslint-rules';
11
11
  exports.WORKSPACE_PLUGIN_DIR = 'tools/eslint-rules';
12
12
  async function lintWorkspaceRulesProjectGenerator(tree, options = {}) {
13
- const { addPropertyToJestConfig, configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/jest', versions_1.nxVersion);
13
+ const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/jest', versions_1.nxVersion);
14
+ const tasks = [];
14
15
  // Noop if the workspace rules project already exists
15
16
  try {
16
17
  (0, devkit_1.readProjectConfiguration)(tree, exports.WORKSPACE_RULES_PROJECT_NAME);
@@ -39,15 +40,16 @@ async function lintWorkspaceRulesProjectGenerator(tree, options = {}) {
39
40
  (0, devkit_1.updateNxJson)(tree, nxJson);
40
41
  }
41
42
  // Add jest to the project and return installation task
42
- const installTask = await configurationGenerator(tree, {
43
+ tasks.push(await configurationGenerator(tree, {
43
44
  project: exports.WORKSPACE_RULES_PROJECT_NAME,
44
45
  supportTsx: false,
45
46
  skipSerializers: true,
46
47
  setupFile: 'none',
47
48
  compiler: 'tsc',
48
49
  skipFormat: true,
49
- });
50
+ }));
50
51
  (0, devkit_1.updateJson)(tree, (0, path_1.join)(workspace_lint_rules_1.workspaceLintPluginDir, 'tsconfig.spec.json'), (json) => {
52
+ delete json.compilerOptions?.module;
51
53
  if (json.include) {
52
54
  json.include = json.include.map((v) => {
53
55
  if (v.startsWith('src/**')) {
@@ -67,14 +69,13 @@ async function lintWorkspaceRulesProjectGenerator(tree, options = {}) {
67
69
  return json;
68
70
  });
69
71
  // Add swc dependencies
70
- (0, add_swc_dependencies_1.addSwcRegisterDependencies)(tree);
71
- // Add extra config to the jest.config.ts file to allow ESLint 8 exports mapping to work with jest
72
- addPropertyToJestConfig(tree, (0, devkit_1.joinPathFragments)(exports.WORKSPACE_PLUGIN_DIR, 'jest.config.ts'), 'moduleNameMapper', {
73
- '@eslint/eslintrc': '@eslint/eslintrc/dist/eslintrc-universal.cjs',
74
- });
72
+ tasks.push((0, add_swc_dependencies_1.addSwcRegisterDependencies)(tree));
73
+ tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
74
+ '@typescript-eslint/utils': versions_1.typescriptESLintVersion,
75
+ }));
75
76
  if (!options.skipFormat) {
76
77
  await (0, devkit_1.formatFiles)(tree);
77
78
  }
78
- return installTask;
79
+ return (0, devkit_1.runTasksInSerial)(...tasks);
79
80
  }
80
81
  exports.lintWorkspaceRulesProjectGenerator = lintWorkspaceRulesProjectGenerator;
@@ -0,0 +1,2 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export default function update(tree: Tree): Promise<void>;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const versions_1 = require("../../utils/versions");
5
+ const path_1 = require("path");
6
+ const typescript_1 = require("typescript");
7
+ function updateJestConfig(tree) {
8
+ const jestConfigPath = 'tools/eslint-rules/jest.config.ts';
9
+ if (tree.exists(jestConfigPath)) {
10
+ const { removePropertyFromJestConfig } = (0, devkit_1.ensurePackage)('@nx/jest', versions_1.nxVersion);
11
+ removePropertyFromJestConfig(tree, jestConfigPath, [
12
+ 'moduleNameMapper',
13
+ '@eslint/eslintrc',
14
+ ]);
15
+ }
16
+ }
17
+ function updateTsConfigs(tree) {
18
+ const tsConfigPath = 'tools/eslint-rules/tsconfig.json';
19
+ if (tree.exists(tsConfigPath)) {
20
+ (0, devkit_1.updateJson)(tree, tsConfigPath, (tsConfig) => {
21
+ tsConfig.compilerOptions ??= {};
22
+ tsConfig.compilerOptions.moduleResolution = 'node16';
23
+ tsConfig.compilerOptions.module = 'node16';
24
+ return tsConfig;
25
+ });
26
+ }
27
+ const tsConfigSpec = 'tools/eslint-rules/tsconfig.spec.json';
28
+ if (tree.exists(tsConfigSpec)) {
29
+ (0, devkit_1.updateJson)(tree, tsConfigSpec, (tsConfigSpec) => {
30
+ delete tsConfigSpec.compilerOptions?.module;
31
+ delete tsConfigSpec.compilerOptions?.moduleResolution;
32
+ return tsConfigSpec;
33
+ });
34
+ }
35
+ }
36
+ function updateRecommended(tree) {
37
+ (0, devkit_1.visitNotIgnoredFiles)(tree, 'tools/eslint-rules', (path) => {
38
+ if ((0, path_1.extname)(path) !== '.ts') {
39
+ return;
40
+ }
41
+ const contents = tree.read(path, 'utf-8');
42
+ const sourceFile = (0, typescript_1.createSourceFile)(path, contents, typescript_1.ScriptTarget.ESNext, true);
43
+ const changes = [];
44
+ const visit = (node) => {
45
+ if ((0, typescript_1.isPropertyAssignment)(node) &&
46
+ (0, typescript_1.isIdentifier)(node.name) &&
47
+ node.name.text === 'recommended' &&
48
+ (0, typescript_1.isStringLiteral)(node.initializer)) {
49
+ changes.push({
50
+ type: devkit_1.ChangeType.Delete,
51
+ start: node.initializer.getStart(sourceFile),
52
+ length: node.initializer.getWidth(sourceFile),
53
+ });
54
+ changes.push({
55
+ type: devkit_1.ChangeType.Insert,
56
+ index: node.initializer.getStart(sourceFile),
57
+ text: "'recommended'",
58
+ });
59
+ }
60
+ else {
61
+ (0, typescript_1.forEachChild)(node, visit);
62
+ }
63
+ };
64
+ (0, typescript_1.forEachChild)(sourceFile, visit);
65
+ tree.write(path, (0, devkit_1.applyChangesToString)(contents, changes));
66
+ });
67
+ }
68
+ async function update(tree) {
69
+ updateJestConfig(tree);
70
+ updateTsConfigs(tree);
71
+ updateRecommended(tree);
72
+ await (0, devkit_1.formatFiles)(tree);
73
+ }
74
+ exports.default = update;
@@ -2,4 +2,4 @@ export declare const nxVersion: any;
2
2
  export declare const eslintVersion = "~8.46.0";
3
3
  export declare const eslintrcVersion = "^2.1.1";
4
4
  export declare const eslintConfigPrettierVersion = "^9.0.0";
5
- export declare const typescriptESLintVersion = "^5.60.1";
5
+ export declare const typescriptESLintVersion = "^6.9.1";
@@ -5,4 +5,4 @@ exports.nxVersion = require('../../package.json').version;
5
5
  exports.eslintVersion = '~8.46.0';
6
6
  exports.eslintrcVersion = '^2.1.1';
7
7
  exports.eslintConfigPrettierVersion = '^9.0.0';
8
- exports.typescriptESLintVersion = '^5.60.1';
8
+ exports.typescriptESLintVersion = '^6.9.1';