@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.
- package/migrations.json +40 -0
- package/package.json +4 -4
- package/src/generators/convert-to-flat-config/converters/json-converter.d.ts +1 -1
- package/src/generators/convert-to-flat-config/converters/json-converter.js +6 -6
- package/src/generators/convert-to-flat-config/generator.js +17 -16
- package/src/generators/convert-to-flat-config/schema.d.ts +2 -0
- package/src/generators/convert-to-inferred/convert-to-inferred.js +1 -0
- package/src/generators/init/global-eslint-config.d.ts +1 -1
- package/src/generators/init/global-eslint-config.js +5 -5
- package/src/generators/init/init-migration.d.ts +1 -1
- package/src/generators/init/init-migration.js +15 -5
- package/src/generators/init/init.d.ts +1 -0
- package/src/generators/init/init.js +17 -6
- package/src/generators/lint-project/lint-project.d.ts +1 -0
- package/src/generators/lint-project/lint-project.js +27 -11
- package/src/generators/lint-project/setup-root-eslint.d.ts +1 -0
- package/src/generators/lint-project/setup-root-eslint.js +2 -1
- package/src/generators/utils/eslint-file.d.ts +1 -0
- package/src/generators/utils/eslint-file.js +54 -14
- package/src/generators/utils/flat-config/ast-utils.d.ts +10 -4
- package/src/generators/utils/flat-config/ast-utils.js +328 -59
- package/src/generators/workspace-rules-project/workspace-rules-project.js +2 -1
- package/src/plugins/plugin.js +1 -1
- package/src/utils/config-file.d.ts +2 -1
- package/src/utils/config-file.js +3 -2
- package/src/utils/flat-config.d.ts +1 -0
- package/src/utils/flat-config.js +8 -2
- package/src/utils/versions.d.ts +1 -1
- package/src/utils/versions.js +1 -1
package/migrations.json
CHANGED
@@ -106,6 +106,46 @@
|
|
106
106
|
"version": "^7.16.0"
|
107
107
|
}
|
108
108
|
}
|
109
|
+
},
|
110
|
+
"20.4.0-typescript-eslint": {
|
111
|
+
"version": "20.4.0-beta.1",
|
112
|
+
"requires": {
|
113
|
+
"typescript-eslint": ">8.0.0 <8.19.0"
|
114
|
+
},
|
115
|
+
"packages": {
|
116
|
+
"typescript-eslint": {
|
117
|
+
"version": "^8.19.0"
|
118
|
+
},
|
119
|
+
"@typescript-eslint/parser": {
|
120
|
+
"version": "^8.19.0"
|
121
|
+
},
|
122
|
+
"@typescript-eslint/eslint-plugin": {
|
123
|
+
"version": "^8.19.0"
|
124
|
+
},
|
125
|
+
"@typescript-eslint/utils": {
|
126
|
+
"version": "^8.19.0"
|
127
|
+
}
|
128
|
+
}
|
129
|
+
},
|
130
|
+
"20.4.0-@typescript-eslint": {
|
131
|
+
"version": "20.4.0-beta.1",
|
132
|
+
"requires": {
|
133
|
+
"@typescript-eslint/eslint-plugin": ">8.0.0 <8.19.0"
|
134
|
+
},
|
135
|
+
"packages": {
|
136
|
+
"typescript-eslint": {
|
137
|
+
"version": "^8.19.0"
|
138
|
+
},
|
139
|
+
"@typescript-eslint/parser": {
|
140
|
+
"version": "^8.19.0"
|
141
|
+
},
|
142
|
+
"@typescript-eslint/eslint-plugin": {
|
143
|
+
"version": "^8.19.0"
|
144
|
+
},
|
145
|
+
"@typescript-eslint/utils": {
|
146
|
+
"version": "^8.19.0"
|
147
|
+
}
|
148
|
+
}
|
109
149
|
}
|
110
150
|
}
|
111
151
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nx/eslint",
|
3
|
-
"version": "20.4.0-beta.
|
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,11 +35,11 @@
|
|
35
35
|
"eslint": "^8.0.0 || ^9.0.0"
|
36
36
|
},
|
37
37
|
"dependencies": {
|
38
|
-
"@nx/devkit": "20.4.0-beta.
|
39
|
-
"@nx/js": "20.4.0-beta.
|
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
|
-
"typescript": "~5.
|
42
|
+
"typescript": "~5.7.2"
|
43
43
|
},
|
44
44
|
"peerDependenciesMeta": {
|
45
45
|
"@zkochan/js-yaml": {
|
@@ -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$/,
|
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,
|
41
|
+
convertConfigToFlatConfig(tree, '', eslintFile, `eslint.base.config.${format}`, format);
|
41
42
|
}
|
42
|
-
convertConfigToFlatConfig(tree, '', eslintFile.replace('.base.', '.'),
|
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,
|
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(
|
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(
|
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(
|
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
|
}
|
@@ -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(
|
31
|
-
?
|
32
|
-
:
|
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
|
-
//
|
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
|
-
|
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(
|
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
|
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) {
|
@@ -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.
|
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 ===
|
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(
|
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);
|
@@ -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(
|
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;
|