@nx/eslint 0.0.0-pr-27404-9b7456c → 0.0.0-pr-27809-4160bae
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/package.json +4 -4
- package/src/executors/lint/utility/eslint-utils.js +1 -3
- package/src/generators/convert-to-flat-config/converters/json-converter.js +2 -18
- package/src/generators/convert-to-flat-config/generator.js +12 -10
- package/src/generators/init/global-eslint-config.d.ts +1 -1
- package/src/generators/init/global-eslint-config.js +15 -28
- package/src/generators/init/init-migration.js +1 -6
- package/src/generators/lint-project/lint-project.js +42 -50
- package/src/generators/lint-project/setup-root-eslint.js +0 -19
- package/src/generators/utils/eslint-file.d.ts +3 -10
- package/src/generators/utils/eslint-file.js +24 -79
- package/src/generators/utils/flat-config/ast-utils.d.ts +7 -21
- package/src/generators/utils/flat-config/ast-utils.js +45 -209
- package/src/plugins/plugin.js +2 -6
- package/src/utils/flat-config.d.ts +2 -2
- package/src/utils/flat-config.js +5 -26
- package/src/utils/resolve-eslint-class.d.ts +1 -3
- package/src/utils/resolve-eslint-class.js +14 -11
- package/src/utils/versions.d.ts +0 -3
- package/src/utils/versions.js +1 -5
- package/src/utils/version-utils.d.ts +0 -2
- package/src/utils/version-utils.js +0 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/eslint",
|
|
3
|
-
"version": "0.0.0-pr-
|
|
3
|
+
"version": "0.0.0-pr-27809-4160bae",
|
|
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,12 +35,12 @@
|
|
|
35
35
|
"eslint": "^8.0.0 || ^9.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@nx/devkit": "0.0.0-pr-
|
|
39
|
-
"@nx/js": "0.0.0-pr-
|
|
38
|
+
"@nx/devkit": "0.0.0-pr-27809-4160bae",
|
|
39
|
+
"@nx/js": "0.0.0-pr-27809-4160bae",
|
|
40
40
|
"semver": "^7.5.3",
|
|
41
41
|
"tslib": "^2.3.0",
|
|
42
42
|
"typescript": "~5.4.2",
|
|
43
|
-
"@nx/linter": "0.0.0-pr-
|
|
43
|
+
"@nx/linter": "0.0.0-pr-27809-4160bae"
|
|
44
44
|
},
|
|
45
45
|
"peerDependenciesMeta": {
|
|
46
46
|
"@zkochan/js-yaml": {
|
|
@@ -9,9 +9,7 @@ async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatCon
|
|
|
9
9
|
// todo: add support for eslint.config.mjs,
|
|
10
10
|
'When using the new Flat Config with ESLint, all configs must be named eslint.config.js or eslint.config.cjs and .eslintrc files may not be used. See https://eslint.org/docs/latest/use/configure/configuration-files');
|
|
11
11
|
}
|
|
12
|
-
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)(
|
|
13
|
-
useFlatConfigOverrideVal: useFlatConfig,
|
|
14
|
-
});
|
|
12
|
+
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)(useFlatConfig);
|
|
15
13
|
const eslintOptions = {
|
|
16
14
|
overrideConfigFile: eslintConfigPath,
|
|
17
15
|
fix: !!options.fix,
|
|
@@ -71,18 +71,6 @@ function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths) {
|
|
|
71
71
|
isFlatCompatNeeded = true;
|
|
72
72
|
}
|
|
73
73
|
exportElements.push((0, ast_utils_1.generateFlatOverride)(override));
|
|
74
|
-
// eslint-plugin-import cannot be used with ESLint v9 yet
|
|
75
|
-
// TODO(jack): Once v9 support is released, remove this block.
|
|
76
|
-
// See: https://github.com/import-js/eslint-plugin-import/pull/2996
|
|
77
|
-
if (override.extends === 'plugin:@nx/react') {
|
|
78
|
-
exportElements.push((0, ast_utils_1.generateFlatOverride)({
|
|
79
|
-
rules: {
|
|
80
|
-
'import/first': 'off',
|
|
81
|
-
'import/no-amd': 'off',
|
|
82
|
-
'import/no-webpack-loader-syntax': 'off',
|
|
83
|
-
},
|
|
84
|
-
}));
|
|
85
|
-
}
|
|
86
74
|
});
|
|
87
75
|
}
|
|
88
76
|
if (config.ignorePatterns) {
|
|
@@ -108,13 +96,9 @@ function convertEslintJsonToFlatConfig(tree, root, config, ignorePaths) {
|
|
|
108
96
|
}
|
|
109
97
|
}
|
|
110
98
|
// create the node list and print it to new file
|
|
111
|
-
const nodeList = (0, ast_utils_1.createNodeList)(importsMap, exportElements);
|
|
112
|
-
let content = (0, ast_utils_1.stringifyNodeList)(nodeList);
|
|
113
|
-
if (isFlatCompatNeeded) {
|
|
114
|
-
content = (0, ast_utils_1.addFlatCompatToFlatConfig)(content);
|
|
115
|
-
}
|
|
99
|
+
const nodeList = (0, ast_utils_1.createNodeList)(importsMap, exportElements, isFlatCompatNeeded);
|
|
116
100
|
return {
|
|
117
|
-
content,
|
|
101
|
+
content: (0, ast_utils_1.stringifyNodeList)(nodeList),
|
|
118
102
|
addESLintRC: isFlatCompatNeeded,
|
|
119
103
|
addESLintJS: isESLintJSNeeded,
|
|
120
104
|
};
|
|
@@ -6,6 +6,7 @@ const eslint_file_1 = require("../utils/eslint-file");
|
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const versions_1 = require("../../utils/versions");
|
|
8
8
|
const json_converter_1 = require("./converters/json-converter");
|
|
9
|
+
let shouldInstallDeps = false;
|
|
9
10
|
async function convertToFlatConfigGenerator(tree, options) {
|
|
10
11
|
const eslintFile = (0, eslint_file_1.findEslintFile)(tree);
|
|
11
12
|
if (!eslintFile) {
|
|
@@ -32,7 +33,9 @@ async function convertToFlatConfigGenerator(tree, options) {
|
|
|
32
33
|
if (!options.skipFormat) {
|
|
33
34
|
await (0, devkit_1.formatFiles)(tree);
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
if (shouldInstallDeps) {
|
|
37
|
+
return () => (0, devkit_1.installPackagesTask)(tree);
|
|
38
|
+
}
|
|
36
39
|
}
|
|
37
40
|
exports.default = convertToFlatConfigGenerator;
|
|
38
41
|
function convertRootToFlatConfig(tree, eslintFile) {
|
|
@@ -125,18 +128,17 @@ function processConvertedConfig(tree, root, source, target, { content, addESLint
|
|
|
125
128
|
tree.delete((0, path_1.join)(root, source));
|
|
126
129
|
// save new
|
|
127
130
|
tree.write((0, path_1.join)(root, target), content);
|
|
128
|
-
// These dependencies are required for flat configs that are generated by subsequent app/lib generators.
|
|
129
|
-
const devDependencies = {
|
|
130
|
-
eslint: versions_1.eslint9__eslintVersion,
|
|
131
|
-
'eslint-config-prettier': versions_1.eslintConfigPrettierVersion,
|
|
132
|
-
'typescript-eslint': versions_1.eslint9__typescriptESLintVersion,
|
|
133
|
-
};
|
|
134
131
|
// add missing packages
|
|
135
132
|
if (addESLintRC) {
|
|
136
|
-
|
|
133
|
+
shouldInstallDeps = true;
|
|
134
|
+
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
|
|
135
|
+
'@eslint/eslintrc': versions_1.eslintrcVersion,
|
|
136
|
+
});
|
|
137
137
|
}
|
|
138
138
|
if (addESLintJS) {
|
|
139
|
-
|
|
139
|
+
shouldInstallDeps = true;
|
|
140
|
+
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
|
|
141
|
+
'@eslint/js': versions_1.eslintVersion,
|
|
142
|
+
});
|
|
140
143
|
}
|
|
141
|
-
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies);
|
|
142
144
|
}
|
|
@@ -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: (unitTestRunner?: string, rootProject?: boolean) => string;
|
|
@@ -78,37 +78,24 @@ 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 = (unitTestRunner, rootProject) => {
|
|
82
|
+
const nodeList = (0, ast_utils_1.createNodeList)(new Map(), [], true);
|
|
83
83
|
let content = (0, ast_utils_1.stringifyNodeList)(nodeList);
|
|
84
|
-
content = (0, ast_utils_1.addImportToFlatConfig)(content, '
|
|
85
|
-
content = (0, ast_utils_1.
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
content = (0, ast_utils_1.addImportToFlatConfig)(content, 'nxPlugin', '@nx/eslint-plugin');
|
|
85
|
+
content = (0, ast_utils_1.addPluginsToExportsBlock)(content, [
|
|
86
|
+
{ name: '@nx', varName: 'nxPlugin', imp: '@nx/eslint-plugin' },
|
|
87
|
+
]);
|
|
88
88
|
if (!rootProject) {
|
|
89
|
-
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
enforceBuildableLibDependency: true,
|
|
96
|
-
allow: [
|
|
97
|
-
// This allows a root project to be present without causing lint errors
|
|
98
|
-
// since all projects will depend on this base file.
|
|
99
|
-
'^.*/eslint.base.config.[cm]?js$',
|
|
100
|
-
],
|
|
101
|
-
depConstraints: [
|
|
102
|
-
{ sourceTag: '*', onlyDependOnLibsWithTags: ['*'] },
|
|
103
|
-
],
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
}));
|
|
89
|
+
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(moduleBoundariesOverride));
|
|
90
|
+
}
|
|
91
|
+
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(exports.typeScriptOverride));
|
|
92
|
+
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(exports.javaScriptOverride));
|
|
93
|
+
if (unitTestRunner === 'jest') {
|
|
94
|
+
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(jestOverride));
|
|
108
95
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
96
|
+
// add ignore for .nx folder
|
|
97
|
+
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateAst)({
|
|
98
|
+
ignores: ['.nx'],
|
|
112
99
|
}));
|
|
113
100
|
return content;
|
|
114
101
|
};
|
|
@@ -29,7 +29,7 @@ function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, keepExisti
|
|
|
29
29
|
}, undefined, keepExistingVersions);
|
|
30
30
|
tree.write(tree.exists('eslint.config.js')
|
|
31
31
|
? 'eslint.base.config.js'
|
|
32
|
-
: 'eslint.config.js', (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)());
|
|
32
|
+
: 'eslint.config.js', (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(unitTestRunner));
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
35
|
const eslintFile = (0, eslint_file_1.findEslintFile)(tree, '.');
|
|
@@ -91,11 +91,6 @@ function migrateEslintFile(projectEslintPath, tree) {
|
|
|
91
91
|
'plugin:@nrwl/typescript',
|
|
92
92
|
'plugin:@nrwl/javascript',
|
|
93
93
|
]);
|
|
94
|
-
config = (0, ast_utils_1.removePredefinedConfigs)(config, '@nx/eslint-plugin', 'nx', [
|
|
95
|
-
'flat/base',
|
|
96
|
-
'flat/typescript',
|
|
97
|
-
'flat/javascript',
|
|
98
|
-
]);
|
|
99
94
|
tree.write(projectEslintPath, config);
|
|
100
95
|
}
|
|
101
96
|
else {
|
|
@@ -114,63 +114,55 @@ function createEsLintConfiguration(tree, options, projectConfig, setParserOption
|
|
|
114
114
|
const pathToRootConfig = extendedRootConfig
|
|
115
115
|
? `${(0, devkit_1.offsetFromRoot)(projectConfig.root)}${extendedRootConfig}`
|
|
116
116
|
: undefined;
|
|
117
|
-
const addDependencyChecks =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
},
|
|
157
|
-
];
|
|
158
|
-
if (addDependencyChecks) {
|
|
117
|
+
const addDependencyChecks = isBuildableLibraryProject(projectConfig);
|
|
118
|
+
const overrides = [
|
|
119
|
+
{
|
|
120
|
+
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
|
121
|
+
/**
|
|
122
|
+
* NOTE: We no longer set parserOptions.project by default when creating new projects.
|
|
123
|
+
*
|
|
124
|
+
* We have observed that users rarely add rules requiring type-checking to their Nx workspaces, and therefore
|
|
125
|
+
* do not actually need the capabilites which parserOptions.project provides. When specifying parserOptions.project,
|
|
126
|
+
* typescript-eslint needs to create full TypeScript Programs for you. When omitting it, it can perform a simple
|
|
127
|
+
* parse (and AST tranformation) of the source files it encounters during a lint run, which is much faster and much
|
|
128
|
+
* less memory intensive.
|
|
129
|
+
*
|
|
130
|
+
* In the rare case that users attempt to add rules requiring type-checking to their setup later on (and haven't set
|
|
131
|
+
* parserOptions.project), the executor will attempt to look for the particular error typescript-eslint gives you
|
|
132
|
+
* and provide feedback to the user.
|
|
133
|
+
*/
|
|
134
|
+
parserOptions: !setParserOptionsProject
|
|
135
|
+
? undefined
|
|
136
|
+
: {
|
|
137
|
+
project: [`${projectConfig.root}/tsconfig.*?.json`],
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* Having an empty rules object present makes it more obvious to the user where they would
|
|
141
|
+
* extend things from if they needed to
|
|
142
|
+
*/
|
|
143
|
+
rules: {},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
files: ['*.ts', '*.tsx'],
|
|
147
|
+
rules: {},
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
files: ['*.js', '*.jsx'],
|
|
151
|
+
rules: {},
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
if (options.addPackageJsonDependencyChecks ||
|
|
155
|
+
isBuildableLibraryProject(projectConfig)) {
|
|
159
156
|
overrides.push({
|
|
160
157
|
files: ['*.json'],
|
|
161
158
|
parser: 'jsonc-eslint-parser',
|
|
162
159
|
rules: {
|
|
163
|
-
'@nx/dependency-checks':
|
|
164
|
-
'error',
|
|
165
|
-
{
|
|
166
|
-
// With flat configs, we don't want to include imports in the eslint js/cjs/mjs files to be checked
|
|
167
|
-
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'],
|
|
168
|
-
},
|
|
169
|
-
],
|
|
160
|
+
'@nx/dependency-checks': 'error',
|
|
170
161
|
},
|
|
171
162
|
});
|
|
172
163
|
}
|
|
173
164
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
165
|
+
const isCompatNeeded = addDependencyChecks;
|
|
174
166
|
const nodes = [];
|
|
175
167
|
const importMap = new Map();
|
|
176
168
|
if (extendedRootConfig) {
|
|
@@ -180,7 +172,7 @@ function createEsLintConfiguration(tree, options, projectConfig, setParserOption
|
|
|
180
172
|
overrides.forEach((override) => {
|
|
181
173
|
nodes.push((0, ast_utils_1.generateFlatOverride)(override));
|
|
182
174
|
});
|
|
183
|
-
const nodeList = (0, ast_utils_1.createNodeList)(importMap, nodes);
|
|
175
|
+
const nodeList = (0, ast_utils_1.createNodeList)(importMap, nodes, isCompatNeeded);
|
|
184
176
|
const content = (0, ast_utils_1.stringifyNodeList)(nodeList);
|
|
185
177
|
tree.write((0, path_1.join)(projectConfig.root, 'eslint.config.js'), content);
|
|
186
178
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setupRootEsLint = setupRootEsLint;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const flat_config_1 = require("../../utils/flat-config");
|
|
6
5
|
const versions_1 = require("../../utils/versions");
|
|
7
6
|
const global_eslint_config_1 = require("../init/global-eslint-config");
|
|
8
7
|
const eslint_file_1 = require("../utils/eslint-file");
|
|
@@ -11,12 +10,6 @@ function setupRootEsLint(tree, options) {
|
|
|
11
10
|
if (rootEslintFile) {
|
|
12
11
|
return () => { };
|
|
13
12
|
}
|
|
14
|
-
if (!(0, flat_config_1.useFlatConfig)(tree)) {
|
|
15
|
-
return setUpLegacyRootEslintRc(tree, options);
|
|
16
|
-
}
|
|
17
|
-
return setUpRootFlatConfig(tree, options);
|
|
18
|
-
}
|
|
19
|
-
function setUpLegacyRootEslintRc(tree, options) {
|
|
20
13
|
(0, devkit_1.writeJson)(tree, '.eslintrc.json', (0, global_eslint_config_1.getGlobalEsLintConfiguration)(options.unitTestRunner, options.rootProject));
|
|
21
14
|
if (tree.exists('.eslintignore')) {
|
|
22
15
|
let content = tree.read('.eslintignore', 'utf-8');
|
|
@@ -37,15 +30,3 @@ function setUpLegacyRootEslintRc(tree, options) {
|
|
|
37
30
|
})
|
|
38
31
|
: () => { };
|
|
39
32
|
}
|
|
40
|
-
function setUpRootFlatConfig(tree, options) {
|
|
41
|
-
tree.write('eslint.config.js', (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(options.rootProject));
|
|
42
|
-
return !options.skipPackageJson
|
|
43
|
-
? (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
|
|
44
|
-
'@eslint/js': versions_1.eslint9__eslintVersion,
|
|
45
|
-
'@nx/eslint-plugin': versions_1.nxVersion,
|
|
46
|
-
eslint: versions_1.eslint9__eslintVersion,
|
|
47
|
-
'eslint-config-prettier': versions_1.eslintConfigPrettierVersion,
|
|
48
|
-
'typescript-eslint': versions_1.eslint9__typescriptESLintVersion,
|
|
49
|
-
})
|
|
50
|
-
: () => { };
|
|
51
|
-
}
|
|
@@ -1,23 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Tree } from '@nx/devkit';
|
|
2
2
|
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 addOverrideToLintConfig(tree: Tree, root: string, override:
|
|
6
|
+
export declare function addOverrideToLintConfig(tree: Tree, root: string, override: Linter.ConfigOverride<Linter.RulesRecord>, options?: {
|
|
7
7
|
insertAtTheEnd?: boolean;
|
|
8
8
|
checkBaseConfig?: boolean;
|
|
9
9
|
}): void;
|
|
10
10
|
export declare function updateOverrideInLintConfig(tree: Tree, root: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean, update: (override: Linter.ConfigOverride<Linter.RulesRecord>) => Linter.ConfigOverride<Linter.RulesRecord>): void;
|
|
11
11
|
export declare function lintConfigHasOverride(tree: Tree, root: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean, checkBaseConfig?: boolean): boolean;
|
|
12
12
|
export declare function replaceOverridesInLintConfig(tree: Tree, root: string, overrides: Linter.ConfigOverride<Linter.RulesRecord>[]): void;
|
|
13
|
-
export declare function addExtendsToLintConfig(tree: Tree, root: string, plugin: string |
|
|
14
|
-
name: string;
|
|
15
|
-
needCompatFixup: boolean;
|
|
16
|
-
} | Array<string | {
|
|
17
|
-
name: string;
|
|
18
|
-
needCompatFixup: boolean;
|
|
19
|
-
}>, insertAtTheEnd?: boolean): GeneratorCallback;
|
|
20
|
-
export declare function addPredefinedConfigToFlatLintConfig(tree: Tree, root: string, predefinedConfigName: string, moduleName?: string, moduleImportPath?: string, spread?: boolean, insertAtTheEnd?: boolean): void;
|
|
13
|
+
export declare function addExtendsToLintConfig(tree: Tree, root: string, plugin: string | string[]): void;
|
|
21
14
|
export declare function addPluginsToLintConfig(tree: Tree, root: string, plugin: string | string[]): void;
|
|
22
15
|
export declare function addIgnoresToLintConfig(tree: Tree, root: string, ignorePatterns: string[]): void;
|
|
23
16
|
export declare function getPluginImport(pluginName: string): string;
|
|
@@ -8,18 +8,14 @@ exports.updateOverrideInLintConfig = updateOverrideInLintConfig;
|
|
|
8
8
|
exports.lintConfigHasOverride = lintConfigHasOverride;
|
|
9
9
|
exports.replaceOverridesInLintConfig = replaceOverridesInLintConfig;
|
|
10
10
|
exports.addExtendsToLintConfig = addExtendsToLintConfig;
|
|
11
|
-
exports.addPredefinedConfigToFlatLintConfig = addPredefinedConfigToFlatLintConfig;
|
|
12
11
|
exports.addPluginsToLintConfig = addPluginsToLintConfig;
|
|
13
12
|
exports.addIgnoresToLintConfig = addIgnoresToLintConfig;
|
|
14
13
|
exports.getPluginImport = getPluginImport;
|
|
15
14
|
const devkit_1 = require("@nx/devkit");
|
|
16
|
-
const semver_1 = require("semver");
|
|
17
|
-
const config_file_1 = require("../../utils/config-file");
|
|
18
15
|
const flat_config_1 = require("../../utils/flat-config");
|
|
19
|
-
const version_utils_1 = require("../../utils/version-utils");
|
|
20
|
-
const versions_1 = require("../../utils/versions");
|
|
21
16
|
const ast_utils_1 = require("./flat-config/ast-utils");
|
|
22
17
|
const path_utils_1 = require("./flat-config/path-utils");
|
|
18
|
+
const config_file_1 = require("../../utils/config-file");
|
|
23
19
|
function findEslintFile(tree, projectRoot) {
|
|
24
20
|
if (projectRoot === undefined && tree.exists(config_file_1.baseEsLintConfigFile)) {
|
|
25
21
|
return config_file_1.baseEsLintConfigFile;
|
|
@@ -114,12 +110,12 @@ function addOverrideToLintConfig(tree, root, override, options = {
|
|
|
114
110
|
}) {
|
|
115
111
|
const isBase = options.checkBaseConfig && findEslintFile(tree, root).includes('.base');
|
|
116
112
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
117
|
-
const fileName = (0, devkit_1.joinPathFragments)(root, isBase ? config_file_1.baseEsLintFlatConfigFile : (0, flat_config_1.
|
|
113
|
+
const fileName = (0, devkit_1.joinPathFragments)(root, isBase ? config_file_1.baseEsLintFlatConfigFile : (0, flat_config_1.flatConfigEslintFilename)(tree));
|
|
118
114
|
const flatOverride = (0, ast_utils_1.generateFlatOverride)(override);
|
|
119
115
|
let content = tree.read(fileName, 'utf8');
|
|
120
|
-
//
|
|
121
|
-
if (
|
|
122
|
-
content = (0, ast_utils_1.
|
|
116
|
+
// we will be using compat here so we need to make sure it's added
|
|
117
|
+
if (overrideNeedsCompat(override)) {
|
|
118
|
+
content = (0, ast_utils_1.addCompatToFlatConfig)(content);
|
|
123
119
|
}
|
|
124
120
|
tree.write(fileName, (0, ast_utils_1.addBlockToFlatConfigExport)(content, flatOverride, options));
|
|
125
121
|
}
|
|
@@ -137,9 +133,12 @@ function addOverrideToLintConfig(tree, root, override, options = {
|
|
|
137
133
|
});
|
|
138
134
|
}
|
|
139
135
|
}
|
|
136
|
+
function overrideNeedsCompat(override) {
|
|
137
|
+
return (override.env || override.extends || override.plugins || override.parser);
|
|
138
|
+
}
|
|
140
139
|
function updateOverrideInLintConfig(tree, root, lookup, update) {
|
|
141
140
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
142
|
-
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.
|
|
141
|
+
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.flatConfigEslintFilename)(tree));
|
|
143
142
|
let content = tree.read(fileName, 'utf8');
|
|
144
143
|
content = (0, ast_utils_1.replaceOverride)(content, root, lookup, update);
|
|
145
144
|
tree.write(fileName, content);
|
|
@@ -174,7 +173,7 @@ function lintConfigHasOverride(tree, root, lookup, checkBaseConfig = false) {
|
|
|
174
173
|
}
|
|
175
174
|
const isBase = checkBaseConfig && findEslintFile(tree, root).includes('.base');
|
|
176
175
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
177
|
-
const fileName = (0, devkit_1.joinPathFragments)(root, isBase ? config_file_1.baseEsLintFlatConfigFile : (0, flat_config_1.
|
|
176
|
+
const fileName = (0, devkit_1.joinPathFragments)(root, isBase ? config_file_1.baseEsLintFlatConfigFile : (0, flat_config_1.flatConfigEslintFilename)(tree));
|
|
178
177
|
const content = tree.read(fileName, 'utf8');
|
|
179
178
|
return (0, ast_utils_1.hasOverride)(content, lookup);
|
|
180
179
|
}
|
|
@@ -185,11 +184,11 @@ function lintConfigHasOverride(tree, root, lookup, checkBaseConfig = false) {
|
|
|
185
184
|
}
|
|
186
185
|
function replaceOverridesInLintConfig(tree, root, overrides) {
|
|
187
186
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
188
|
-
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.
|
|
187
|
+
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.flatConfigEslintFilename)(tree));
|
|
189
188
|
let content = tree.read(fileName, 'utf8');
|
|
190
|
-
//
|
|
191
|
-
if (overrides.some(
|
|
192
|
-
content = (0, ast_utils_1.
|
|
189
|
+
// we will be using compat here so we need to make sure it's added
|
|
190
|
+
if (overrides.some(overrideNeedsCompat)) {
|
|
191
|
+
content = (0, ast_utils_1.addCompatToFlatConfig)(content);
|
|
193
192
|
}
|
|
194
193
|
content = (0, ast_utils_1.removeOverridesFromLintConfig)(content);
|
|
195
194
|
overrides.forEach((override) => {
|
|
@@ -206,62 +205,18 @@ function replaceOverridesInLintConfig(tree, root, overrides) {
|
|
|
206
205
|
});
|
|
207
206
|
}
|
|
208
207
|
}
|
|
209
|
-
function addExtendsToLintConfig(tree, root, plugin
|
|
208
|
+
function addExtendsToLintConfig(tree, root, plugin) {
|
|
209
|
+
const plugins = Array.isArray(plugin) ? plugin : [plugin];
|
|
210
210
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
let shouldImportEslintCompat = false;
|
|
214
|
-
// assume eslint version is 9 if not found, as it's what we'd be generating by default
|
|
215
|
-
const eslintVersion = (0, version_utils_1.getInstalledEslintVersion)(tree) ?? versions_1.eslint9__eslintVersion;
|
|
216
|
-
if ((0, semver_1.gte)(eslintVersion, '9.0.0')) {
|
|
217
|
-
// eslint v9 requires the incompatible plugins to be wrapped with a helper from @eslint/compat
|
|
218
|
-
const plugins = (Array.isArray(plugin) ? plugin : [plugin]).map((p) => typeof p === 'string' ? { name: p, needCompatFixup: false } : p);
|
|
219
|
-
let compatiblePluginsBatch = [];
|
|
220
|
-
plugins.forEach(({ name, needCompatFixup }) => {
|
|
221
|
-
if (needCompatFixup) {
|
|
222
|
-
if (compatiblePluginsBatch.length > 0) {
|
|
223
|
-
// flush the current batch of compatible plugins and reset it
|
|
224
|
-
pluginExtends.push((0, ast_utils_1.generatePluginExtendsElement)(compatiblePluginsBatch));
|
|
225
|
-
compatiblePluginsBatch = [];
|
|
226
|
-
}
|
|
227
|
-
// generate the extends for the incompatible plugin
|
|
228
|
-
pluginExtends.push((0, ast_utils_1.generatePluginExtendsElementWithCompatFixup)(name));
|
|
229
|
-
shouldImportEslintCompat = true;
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
// add the compatible plugin to the current batch
|
|
233
|
-
compatiblePluginsBatch.push(name);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
if (compatiblePluginsBatch.length > 0) {
|
|
237
|
-
// flush the batch of compatible plugins
|
|
238
|
-
pluginExtends.push((0, ast_utils_1.generatePluginExtendsElement)(compatiblePluginsBatch));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
const plugins = (Array.isArray(plugin) ? plugin : [plugin]).map((p) => typeof p === 'string' ? p : p.name);
|
|
243
|
-
pluginExtends.push((0, ast_utils_1.generatePluginExtendsElement)(plugins));
|
|
244
|
-
}
|
|
211
|
+
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.flatConfigEslintFilename)(tree));
|
|
212
|
+
const pluginExtends = (0, ast_utils_1.generatePluginExtendsElement)(plugins);
|
|
245
213
|
let content = tree.read(fileName, 'utf8');
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// reverse the order to ensure they are added in the correct order at the
|
|
251
|
-
// start of the `extends` array
|
|
252
|
-
for (const pluginExtend of pluginExtends.reverse()) {
|
|
253
|
-
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, pluginExtend, {
|
|
254
|
-
insertAtTheEnd,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
tree.write(fileName, content);
|
|
258
|
-
if (shouldImportEslintCompat) {
|
|
259
|
-
return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@eslint/compat': versions_1.eslintCompat }, undefined, true);
|
|
260
|
-
}
|
|
261
|
-
return () => { };
|
|
214
|
+
content = (0, ast_utils_1.addCompatToFlatConfig)(content);
|
|
215
|
+
tree.write(fileName, (0, ast_utils_1.addBlockToFlatConfigExport)(content, pluginExtends, {
|
|
216
|
+
insertAtTheEnd: false,
|
|
217
|
+
}));
|
|
262
218
|
}
|
|
263
219
|
else {
|
|
264
|
-
const plugins = (Array.isArray(plugin) ? plugin : [plugin]).map((p) => typeof p === 'string' ? p : p.name);
|
|
265
220
|
const fileName = (0, devkit_1.joinPathFragments)(root, '.eslintrc.json');
|
|
266
221
|
(0, devkit_1.updateJson)(tree, fileName, (json) => {
|
|
267
222
|
json.extends ??= [];
|
|
@@ -271,22 +226,12 @@ function addExtendsToLintConfig(tree, root, plugin, insertAtTheEnd = false) {
|
|
|
271
226
|
];
|
|
272
227
|
return json;
|
|
273
228
|
});
|
|
274
|
-
return () => { };
|
|
275
229
|
}
|
|
276
230
|
}
|
|
277
|
-
function addPredefinedConfigToFlatLintConfig(tree, root, predefinedConfigName, moduleName = 'nx', moduleImportPath = '@nx/eslint-plugin', spread = true, insertAtTheEnd = true) {
|
|
278
|
-
if (!(0, flat_config_1.useFlatConfig)(tree))
|
|
279
|
-
throw new Error('Predefined configs can only be used with flat configs');
|
|
280
|
-
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.getRootESLintFlatConfigFilename)(tree));
|
|
281
|
-
let content = tree.read(fileName, 'utf8');
|
|
282
|
-
content = (0, ast_utils_1.addImportToFlatConfig)(content, moduleName, moduleImportPath);
|
|
283
|
-
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatPredefinedConfig)(predefinedConfigName, moduleName, spread), { insertAtTheEnd });
|
|
284
|
-
tree.write(fileName, content);
|
|
285
|
-
}
|
|
286
231
|
function addPluginsToLintConfig(tree, root, plugin) {
|
|
287
232
|
const plugins = Array.isArray(plugin) ? plugin : [plugin];
|
|
288
233
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
289
|
-
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.
|
|
234
|
+
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.flatConfigEslintFilename)(tree));
|
|
290
235
|
let content = tree.read(fileName, 'utf8');
|
|
291
236
|
const mappedPlugins = [];
|
|
292
237
|
plugins.forEach((name) => {
|
|
@@ -310,7 +255,7 @@ function addPluginsToLintConfig(tree, root, plugin) {
|
|
|
310
255
|
}
|
|
311
256
|
function addIgnoresToLintConfig(tree, root, ignorePatterns) {
|
|
312
257
|
if ((0, flat_config_1.useFlatConfig)(tree)) {
|
|
313
|
-
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.
|
|
258
|
+
const fileName = (0, devkit_1.joinPathFragments)(root, (0, flat_config_1.flatConfigEslintFilename)(tree));
|
|
314
259
|
const block = (0, ast_utils_1.generateAst)({
|
|
315
260
|
ignores: ignorePatterns.map((path) => (0, path_utils_1.mapFilePath)(path)),
|
|
316
261
|
});
|
|
@@ -8,15 +8,11 @@ export declare function hasOverride(content: string, lookup: (override: Linter.C
|
|
|
8
8
|
/**
|
|
9
9
|
* Finds an override matching the lookup function and applies the update function to it
|
|
10
10
|
*/
|
|
11
|
-
export declare function replaceOverride(content: string, root: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean, update?: (override:
|
|
11
|
+
export declare function replaceOverride(content: string, root: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean, update?: (override: Linter.ConfigOverride<Linter.RulesRecord>) => Linter.ConfigOverride<Linter.RulesRecord>): string;
|
|
12
12
|
/**
|
|
13
13
|
* Adding require statement to the top of the file
|
|
14
14
|
*/
|
|
15
15
|
export declare function addImportToFlatConfig(content: string, variable: string | string[], imp: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* Remove an import from flat config
|
|
18
|
-
*/
|
|
19
|
-
export declare function removeImportFromFlatConfig(content: string, variable: string, imp: string): string;
|
|
20
16
|
/**
|
|
21
17
|
* Injects new ts.expression to the end of the module.exports array.
|
|
22
18
|
*/
|
|
@@ -26,7 +22,6 @@ export declare function addBlockToFlatConfigExport(content: string, config: ts.E
|
|
|
26
22
|
}): string;
|
|
27
23
|
export declare function removePlugin(content: string, pluginName: string, pluginImport: string): string;
|
|
28
24
|
export declare function removeCompatExtends(content: string, compatExtends: string[]): string;
|
|
29
|
-
export declare function removePredefinedConfigs(content: string, moduleImport: string, moduleVariable: string, configs: string[]): string;
|
|
30
25
|
/**
|
|
31
26
|
* Add plugins block to the top of the export blocks
|
|
32
27
|
*/
|
|
@@ -38,15 +33,14 @@ export declare function addPluginsToExportsBlock(content: string, plugins: {
|
|
|
38
33
|
/**
|
|
39
34
|
* Adds compat if missing to flat config
|
|
40
35
|
*/
|
|
41
|
-
export declare function
|
|
36
|
+
export declare function addCompatToFlatConfig(content: string): string;
|
|
42
37
|
/**
|
|
43
38
|
* Generate node list representing the imports and the exports blocks
|
|
44
39
|
* Optionally add flat compat initialization
|
|
45
40
|
*/
|
|
46
|
-
export declare function createNodeList(importsMap: Map<string, string>, exportElements: ts.Expression[]): ts.NodeArray<ts.VariableStatement | ts.Identifier | ts.ExpressionStatement | ts.SourceFile>;
|
|
41
|
+
export declare function createNodeList(importsMap: Map<string, string>, exportElements: ts.Expression[], isFlatCompatNeeded: boolean): ts.NodeArray<ts.VariableStatement | ts.Identifier | ts.ExpressionStatement | ts.SourceFile>;
|
|
47
42
|
export declare function generateSpreadElement(name: string): ts.SpreadElement;
|
|
48
43
|
export declare function generatePluginExtendsElement(plugins: string[]): ts.SpreadElement;
|
|
49
|
-
export declare function generatePluginExtendsElementWithCompatFixup(plugin: string): ts.SpreadElement;
|
|
50
44
|
/**
|
|
51
45
|
* Stringifies TS nodes to file content string
|
|
52
46
|
*/
|
|
@@ -55,20 +49,12 @@ export declare function stringifyNodeList(nodes: ts.NodeArray<ts.VariableStateme
|
|
|
55
49
|
* generates AST require statement
|
|
56
50
|
*/
|
|
57
51
|
export declare function generateRequire(variableName: string | ts.ObjectBindingPattern, imp: string): ts.VariableStatement;
|
|
58
|
-
export declare function overrideNeedsCompat(override: Partial<Linter.ConfigOverride<Linter.RulesRecord>>): string | string[] | {
|
|
59
|
-
[name: string]: boolean;
|
|
60
|
-
};
|
|
61
52
|
/**
|
|
62
|
-
* Generates
|
|
63
|
-
* based on a given legacy eslintrc JSON override object
|
|
53
|
+
* Generates AST object or spread element based on JSON override object
|
|
64
54
|
*/
|
|
65
|
-
export declare function generateFlatOverride(
|
|
66
|
-
export declare function
|
|
67
|
-
export declare function mapFilePaths(_override: Partial<Linter.ConfigOverride<Linter.RulesRecord>>): Partial<Linter.ConfigOverride<Linter.RulesRecord>>;
|
|
55
|
+
export declare function generateFlatOverride(override: Linter.ConfigOverride<Linter.RulesRecord>): ts.ObjectLiteralExpression | ts.SpreadElement;
|
|
56
|
+
export declare function mapFilePaths(override: Linter.ConfigOverride<Linter.RulesRecord>): void;
|
|
68
57
|
/**
|
|
69
58
|
* Generates an AST from a JSON-type input
|
|
70
59
|
*/
|
|
71
|
-
export declare function generateAst<T>(input: unknown
|
|
72
|
-
keyToMatch: RegExp | string;
|
|
73
|
-
replacer: (propertyAssignment: ts.PropertyAssignment, propertyName: string) => ts.PropertyAssignment;
|
|
74
|
-
}): T;
|
|
60
|
+
export declare function generateAst<T>(input: unknown): T;
|
|
@@ -4,22 +4,17 @@ exports.removeOverridesFromLintConfig = removeOverridesFromLintConfig;
|
|
|
4
4
|
exports.hasOverride = hasOverride;
|
|
5
5
|
exports.replaceOverride = replaceOverride;
|
|
6
6
|
exports.addImportToFlatConfig = addImportToFlatConfig;
|
|
7
|
-
exports.removeImportFromFlatConfig = removeImportFromFlatConfig;
|
|
8
7
|
exports.addBlockToFlatConfigExport = addBlockToFlatConfigExport;
|
|
9
8
|
exports.removePlugin = removePlugin;
|
|
10
9
|
exports.removeCompatExtends = removeCompatExtends;
|
|
11
|
-
exports.removePredefinedConfigs = removePredefinedConfigs;
|
|
12
10
|
exports.addPluginsToExportsBlock = addPluginsToExportsBlock;
|
|
13
|
-
exports.
|
|
11
|
+
exports.addCompatToFlatConfig = addCompatToFlatConfig;
|
|
14
12
|
exports.createNodeList = createNodeList;
|
|
15
13
|
exports.generateSpreadElement = generateSpreadElement;
|
|
16
14
|
exports.generatePluginExtendsElement = generatePluginExtendsElement;
|
|
17
|
-
exports.generatePluginExtendsElementWithCompatFixup = generatePluginExtendsElementWithCompatFixup;
|
|
18
15
|
exports.stringifyNodeList = stringifyNodeList;
|
|
19
16
|
exports.generateRequire = generateRequire;
|
|
20
|
-
exports.overrideNeedsCompat = overrideNeedsCompat;
|
|
21
17
|
exports.generateFlatOverride = generateFlatOverride;
|
|
22
|
-
exports.generateFlatPredefinedConfig = generateFlatPredefinedConfig;
|
|
23
18
|
exports.mapFilePaths = mapFilePaths;
|
|
24
19
|
exports.generateAst = generateAst;
|
|
25
20
|
const devkit_1 = require("@nx/devkit");
|
|
@@ -91,7 +86,10 @@ function hasOverride(content, lookup) {
|
|
|
91
86
|
// strip any spread elements
|
|
92
87
|
objSource = fullNodeText.replace(SPREAD_ELEMENTS_REGEXP, '');
|
|
93
88
|
}
|
|
94
|
-
const data =
|
|
89
|
+
const data = (0, devkit_1.parseJson)(objSource
|
|
90
|
+
// ensure property names have double quotes so that JSON.parse works
|
|
91
|
+
.replace(/'/g, '"')
|
|
92
|
+
.replace(/\s([a-zA-Z0-9_]+)\s*:/g, ' "$1": '));
|
|
95
93
|
if (lookup(data)) {
|
|
96
94
|
return true;
|
|
97
95
|
}
|
|
@@ -103,9 +101,7 @@ function parseTextToJson(text) {
|
|
|
103
101
|
return (0, devkit_1.parseJson)(text
|
|
104
102
|
// ensure property names have double quotes so that JSON.parse works
|
|
105
103
|
.replace(/'/g, '"')
|
|
106
|
-
.replace(/\s([a-zA-Z0-9_]+)\s*:/g, ' "$1": ')
|
|
107
|
-
// stringify any require calls to avoid JSON parsing errors, turn them into just the string value being required
|
|
108
|
-
.replace(/require\(['"]([^'"]+)['"]\)/g, '"$1"'));
|
|
104
|
+
.replace(/\s([a-zA-Z0-9_]+)\s*:/g, ' "$1": '));
|
|
109
105
|
}
|
|
110
106
|
/**
|
|
111
107
|
* Finds an override matching the lookup function and applies the update function to it
|
|
@@ -142,18 +138,13 @@ function replaceOverride(content, root, lookup, update) {
|
|
|
142
138
|
start,
|
|
143
139
|
length: end - start,
|
|
144
140
|
});
|
|
145
|
-
|
|
141
|
+
const updatedData = update(data);
|
|
146
142
|
if (updatedData) {
|
|
147
|
-
|
|
143
|
+
mapFilePaths(updatedData);
|
|
148
144
|
changes.push({
|
|
149
145
|
type: devkit_1.ChangeType.Insert,
|
|
150
146
|
index: start,
|
|
151
|
-
text: JSON.stringify(updatedData, null, 2)
|
|
152
|
-
// restore any parser require calls that were stripped during JSON parsing
|
|
153
|
-
.replace(/"parser": "([^"]+)"/g, (_, parser) => {
|
|
154
|
-
return `"parser": require('${parser}')`;
|
|
155
|
-
})
|
|
156
|
-
.slice(2, -2), // remove curly braces and start/end line breaks since we are injecting just properties
|
|
147
|
+
text: JSON.stringify(updatedData, null, 2).slice(2, -2), // remove curly braces and start/end line breaks since we are injecting just properties
|
|
157
148
|
});
|
|
158
149
|
}
|
|
159
150
|
}
|
|
@@ -235,32 +226,6 @@ function addImportToFlatConfig(content, variable, imp) {
|
|
|
235
226
|
},
|
|
236
227
|
]);
|
|
237
228
|
}
|
|
238
|
-
/**
|
|
239
|
-
* Remove an import from flat config
|
|
240
|
-
*/
|
|
241
|
-
function removeImportFromFlatConfig(content, variable, imp) {
|
|
242
|
-
const source = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
|
243
|
-
const changes = [];
|
|
244
|
-
ts.forEachChild(source, (node) => {
|
|
245
|
-
// we can only combine object binding patterns
|
|
246
|
-
if (ts.isVariableStatement(node) &&
|
|
247
|
-
ts.isVariableDeclaration(node.declarationList.declarations[0]) &&
|
|
248
|
-
ts.isIdentifier(node.declarationList.declarations[0].name) &&
|
|
249
|
-
node.declarationList.declarations[0].name.getText() === variable &&
|
|
250
|
-
ts.isCallExpression(node.declarationList.declarations[0].initializer) &&
|
|
251
|
-
node.declarationList.declarations[0].initializer.expression.getText() ===
|
|
252
|
-
'require' &&
|
|
253
|
-
ts.isStringLiteral(node.declarationList.declarations[0].initializer.arguments[0]) &&
|
|
254
|
-
node.declarationList.declarations[0].initializer.arguments[0].text === imp) {
|
|
255
|
-
changes.push({
|
|
256
|
-
type: devkit_1.ChangeType.Delete,
|
|
257
|
-
start: node.pos,
|
|
258
|
-
length: node.end - node.pos,
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
return (0, devkit_1.applyChangesToString)(content, changes);
|
|
263
|
-
}
|
|
264
229
|
/**
|
|
265
230
|
* Injects new ts.expression to the end of the module.exports array.
|
|
266
231
|
*/
|
|
@@ -277,11 +242,6 @@ function addBlockToFlatConfigExport(content, config, options = {
|
|
|
277
242
|
return node.expression.right.elements;
|
|
278
243
|
}
|
|
279
244
|
});
|
|
280
|
-
// The config is not in the format that we generate with, skip update.
|
|
281
|
-
// This could happen during `init-migration` when extracting config from the base, but
|
|
282
|
-
// base config was not generated by Nx.
|
|
283
|
-
if (!exportsArray)
|
|
284
|
-
return content;
|
|
285
245
|
const insert = printer.printNode(ts.EmitHint.Expression, config, source);
|
|
286
246
|
if (options.insertAtTheEnd) {
|
|
287
247
|
const index = exportsArray.length > 0
|
|
@@ -419,7 +379,7 @@ function removePlugin(content, pluginName, pluginImport) {
|
|
|
419
379
|
function removeCompatExtends(content, compatExtends) {
|
|
420
380
|
const source = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
|
421
381
|
const changes = [];
|
|
422
|
-
findAllBlocks(source)
|
|
382
|
+
findAllBlocks(source).forEach((node) => {
|
|
423
383
|
if (ts.isSpreadElement(node) &&
|
|
424
384
|
ts.isCallExpression(node.expression) &&
|
|
425
385
|
ts.isArrowFunction(node.expression.arguments[0]) &&
|
|
@@ -444,45 +404,13 @@ function removeCompatExtends(content, compatExtends) {
|
|
|
444
404
|
type: devkit_1.ChangeType.Insert,
|
|
445
405
|
index: node.pos,
|
|
446
406
|
text: '\n' +
|
|
447
|
-
body.replace(new RegExp('[ \t]s*...' + paramName + '
|
|
407
|
+
body.replace(new RegExp('[ \t]s*...' + paramName + '[ \t]*,?\\s*', 'g'), ''),
|
|
448
408
|
});
|
|
449
409
|
}
|
|
450
410
|
}
|
|
451
411
|
});
|
|
452
412
|
return (0, devkit_1.applyChangesToString)(content, changes);
|
|
453
413
|
}
|
|
454
|
-
function removePredefinedConfigs(content, moduleImport, moduleVariable, configs) {
|
|
455
|
-
const source = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
|
456
|
-
const changes = [];
|
|
457
|
-
let removeImport = true;
|
|
458
|
-
findAllBlocks(source)?.forEach((node) => {
|
|
459
|
-
if (ts.isSpreadElement(node) &&
|
|
460
|
-
ts.isElementAccessExpression(node.expression) &&
|
|
461
|
-
ts.isPropertyAccessExpression(node.expression.expression) &&
|
|
462
|
-
ts.isIdentifier(node.expression.expression.expression) &&
|
|
463
|
-
node.expression.expression.expression.getText() === moduleVariable &&
|
|
464
|
-
ts.isStringLiteral(node.expression.argumentExpression)) {
|
|
465
|
-
const config = node.expression.argumentExpression.getText();
|
|
466
|
-
// Check the text without quotes
|
|
467
|
-
if (configs.includes(config.substring(1, config.length - 1))) {
|
|
468
|
-
changes.push({
|
|
469
|
-
type: devkit_1.ChangeType.Delete,
|
|
470
|
-
start: node.pos,
|
|
471
|
-
length: node.end - node.pos + 1, // trailing comma
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
else {
|
|
475
|
-
// If there is still a config used, do not remove import
|
|
476
|
-
removeImport = false;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
let updated = (0, devkit_1.applyChangesToString)(content, changes);
|
|
481
|
-
if (removeImport) {
|
|
482
|
-
updated = removeImportFromFlatConfig(updated, moduleVariable, moduleImport);
|
|
483
|
-
}
|
|
484
|
-
return updated;
|
|
485
|
-
}
|
|
486
414
|
/**
|
|
487
415
|
* Add plugins block to the top of the export blocks
|
|
488
416
|
*/
|
|
@@ -499,7 +427,7 @@ function addPluginsToExportsBlock(content, plugins) {
|
|
|
499
427
|
/**
|
|
500
428
|
* Adds compat if missing to flat config
|
|
501
429
|
*/
|
|
502
|
-
function
|
|
430
|
+
function addCompatToFlatConfig(content) {
|
|
503
431
|
let result = content;
|
|
504
432
|
result = addImportToFlatConfig(result, 'js', '@eslint/js');
|
|
505
433
|
if (result.includes('const compat = new FlatCompat')) {
|
|
@@ -511,21 +439,28 @@ function addFlatCompatToFlatConfig(content) {
|
|
|
511
439
|
{
|
|
512
440
|
type: devkit_1.ChangeType.Insert,
|
|
513
441
|
index: index - 1,
|
|
514
|
-
text:
|
|
515
|
-
const compat = new FlatCompat({
|
|
516
|
-
baseDirectory: __dirname,
|
|
517
|
-
recommendedConfig: js.configs.recommended,
|
|
518
|
-
});
|
|
519
|
-
`,
|
|
442
|
+
text: `${DEFAULT_FLAT_CONFIG}\n`,
|
|
520
443
|
},
|
|
521
444
|
]);
|
|
522
445
|
}
|
|
446
|
+
const DEFAULT_FLAT_CONFIG = `
|
|
447
|
+
const compat = new FlatCompat({
|
|
448
|
+
baseDirectory: __dirname,
|
|
449
|
+
recommendedConfig: js.configs.recommended,
|
|
450
|
+
});
|
|
451
|
+
`;
|
|
523
452
|
/**
|
|
524
453
|
* Generate node list representing the imports and the exports blocks
|
|
525
454
|
* Optionally add flat compat initialization
|
|
526
455
|
*/
|
|
527
|
-
function createNodeList(importsMap, exportElements) {
|
|
456
|
+
function createNodeList(importsMap, exportElements, isFlatCompatNeeded) {
|
|
528
457
|
const importsList = [];
|
|
458
|
+
if (isFlatCompatNeeded) {
|
|
459
|
+
importsMap.set('@eslint/js', 'js');
|
|
460
|
+
importsList.push(generateRequire(ts.factory.createObjectBindingPattern([
|
|
461
|
+
ts.factory.createBindingElement(undefined, undefined, 'FlatCompat'),
|
|
462
|
+
]), '@eslint/eslintrc'));
|
|
463
|
+
}
|
|
529
464
|
// generateRequire(varName, imp, ts.factory);
|
|
530
465
|
Array.from(importsMap.entries()).forEach(([imp, varName]) => {
|
|
531
466
|
importsList.push(generateRequire(varName, imp));
|
|
@@ -533,7 +468,7 @@ function createNodeList(importsMap, exportElements) {
|
|
|
533
468
|
return ts.factory.createNodeArray([
|
|
534
469
|
// add plugin imports
|
|
535
470
|
...importsList,
|
|
536
|
-
ts.createSourceFile('', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.JS),
|
|
471
|
+
ts.createSourceFile('', isFlatCompatNeeded ? DEFAULT_FLAT_CONFIG : '', ts.ScriptTarget.Latest, false, ts.ScriptKind.JS),
|
|
537
472
|
// creates:
|
|
538
473
|
// module.exports = [ ... ];
|
|
539
474
|
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('module'), ts.factory.createIdentifier('exports')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createArrayLiteralExpression(exportElements, true))),
|
|
@@ -545,11 +480,6 @@ function generateSpreadElement(name) {
|
|
|
545
480
|
function generatePluginExtendsElement(plugins) {
|
|
546
481
|
return ts.factory.createSpreadElement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('compat'), ts.factory.createIdentifier('extends')), undefined, plugins.map((plugin) => ts.factory.createStringLiteral(plugin))));
|
|
547
482
|
}
|
|
548
|
-
function generatePluginExtendsElementWithCompatFixup(plugin) {
|
|
549
|
-
return ts.factory.createSpreadElement(ts.factory.createCallExpression(ts.factory.createIdentifier('fixupConfigRules'), undefined, [
|
|
550
|
-
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('compat'), ts.factory.createIdentifier('extends')), undefined, [ts.factory.createStringLiteral(plugin)]),
|
|
551
|
-
]));
|
|
552
|
-
}
|
|
553
483
|
/**
|
|
554
484
|
* Stringifies TS nodes to file content string
|
|
555
485
|
*/
|
|
@@ -572,95 +502,21 @@ function generateRequire(variableName, imp) {
|
|
|
572
502
|
], ts.NodeFlags.Const));
|
|
573
503
|
}
|
|
574
504
|
/**
|
|
575
|
-
*
|
|
576
|
-
*
|
|
577
|
-
* Converts a glob pattern to a format that can be used in a flat config.
|
|
578
|
-
* @param {string} pattern The glob pattern to convert.
|
|
579
|
-
* @returns {string} The converted glob pattern.
|
|
580
|
-
*/
|
|
581
|
-
function convertGlobPattern(pattern) {
|
|
582
|
-
const isNegated = pattern.startsWith('!');
|
|
583
|
-
const patternToTest = isNegated ? pattern.slice(1) : pattern;
|
|
584
|
-
// if the pattern is already in the correct format, return it
|
|
585
|
-
if (patternToTest === '**' || patternToTest.includes('/')) {
|
|
586
|
-
return pattern;
|
|
587
|
-
}
|
|
588
|
-
return `${isNegated ? '!' : ''}**/${patternToTest}`;
|
|
589
|
-
}
|
|
590
|
-
// FROM: https://github.com/eslint/rewrite/blob/e2a7ec809db20e638abbad250d105ddbde88a8d5/packages/migrate-config/src/migrate-config.js#L38
|
|
591
|
-
const keysToCopy = ['settings', 'rules', 'processor'];
|
|
592
|
-
function overrideNeedsCompat(override) {
|
|
593
|
-
return override.env || override.extends || override.plugins;
|
|
594
|
-
}
|
|
595
|
-
/**
|
|
596
|
-
* Generates an AST object or spread element representing a modern flat config entry,
|
|
597
|
-
* based on a given legacy eslintrc JSON override object
|
|
505
|
+
* Generates AST object or spread element based on JSON override object
|
|
598
506
|
*/
|
|
599
|
-
function generateFlatOverride(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
if (
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
const flatConfigOverride = {
|
|
609
|
-
files,
|
|
610
|
-
};
|
|
611
|
-
if (override.rules) {
|
|
612
|
-
flatConfigOverride.rules = override.rules;
|
|
507
|
+
function generateFlatOverride(override) {
|
|
508
|
+
mapFilePaths(override);
|
|
509
|
+
if (!override.env &&
|
|
510
|
+
!override.extends &&
|
|
511
|
+
!override.plugins &&
|
|
512
|
+
!override.parser) {
|
|
513
|
+
if (override.parserOptions) {
|
|
514
|
+
const { parserOptions, ...rest } = override;
|
|
515
|
+
return generateAst({ ...rest, languageOptions: { parserOptions } });
|
|
613
516
|
}
|
|
614
|
-
|
|
615
|
-
keysToCopy.forEach((key) => {
|
|
616
|
-
if (override[key]) {
|
|
617
|
-
flatConfigOverride[key] = override[key];
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
if (override.parser || override.parserOptions) {
|
|
621
|
-
const languageOptions = {};
|
|
622
|
-
if (override.parser) {
|
|
623
|
-
languageOptions['parser'] = override.parser;
|
|
624
|
-
}
|
|
625
|
-
if (override.parserOptions) {
|
|
626
|
-
languageOptions['parserOptions'] = override.parserOptions;
|
|
627
|
-
}
|
|
628
|
-
if (Object.keys(languageOptions).length) {
|
|
629
|
-
flatConfigOverride.languageOptions = languageOptions;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
if (override['languageOptions']) {
|
|
633
|
-
flatConfigOverride.languageOptions = override['languageOptions'];
|
|
634
|
-
}
|
|
635
|
-
if (override.excludedFiles) {
|
|
636
|
-
flatConfigOverride.ignores = (Array.isArray(override.excludedFiles)
|
|
637
|
-
? override.excludedFiles
|
|
638
|
-
: [override.excludedFiles]).map((p) => convertGlobPattern(p));
|
|
639
|
-
}
|
|
640
|
-
return generateAst(flatConfigOverride, {
|
|
641
|
-
keyToMatch: /^(parser|rules)$/,
|
|
642
|
-
replacer: (propertyAssignment, propertyName) => {
|
|
643
|
-
if (propertyName === 'rules') {
|
|
644
|
-
// Add comment that user can override rules if there are no overrides.
|
|
645
|
-
if (ts.isObjectLiteralExpression(propertyAssignment.initializer) &&
|
|
646
|
-
propertyAssignment.initializer.properties.length === 0) {
|
|
647
|
-
return ts.addSyntheticLeadingComment(ts.factory.createPropertyAssignment(propertyAssignment.name, ts.factory.createObjectLiteralExpression([])), ts.SyntaxKind.SingleLineCommentTrivia, ' Override or add rules here');
|
|
648
|
-
}
|
|
649
|
-
return propertyAssignment;
|
|
650
|
-
}
|
|
651
|
-
else {
|
|
652
|
-
// Change parser to require statement.
|
|
653
|
-
return ts.factory.createPropertyAssignment('parser', ts.factory.createCallExpression(ts.factory.createIdentifier('require'), undefined, [
|
|
654
|
-
ts.factory.createStringLiteral(override['languageOptions']?.['parserOptions']?.parser ??
|
|
655
|
-
override['languageOptions']?.parser ??
|
|
656
|
-
override.parser),
|
|
657
|
-
]));
|
|
658
|
-
}
|
|
659
|
-
},
|
|
660
|
-
});
|
|
517
|
+
return generateAst(override);
|
|
661
518
|
}
|
|
662
|
-
|
|
663
|
-
const { excludedFiles, parser, parserOptions, rules, files, ...rest } = override;
|
|
519
|
+
const { files, excludedFiles, rules, parserOptions, ...rest } = override;
|
|
664
520
|
const objectLiteralElements = [
|
|
665
521
|
ts.factory.createSpreadAssignment(ts.factory.createIdentifier('config')),
|
|
666
522
|
];
|
|
@@ -687,14 +543,7 @@ function generateFlatOverride(_override) {
|
|
|
687
543
|
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createParenthesizedExpression(ts.factory.createObjectLiteralExpression(objectLiteralElements, true))),
|
|
688
544
|
]));
|
|
689
545
|
}
|
|
690
|
-
function
|
|
691
|
-
const node = ts.factory.createElementAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(moduleName), ts.factory.createIdentifier('configs')), ts.factory.createStringLiteral(predefinedConfigName));
|
|
692
|
-
return spread ? ts.factory.createSpreadElement(node) : node;
|
|
693
|
-
}
|
|
694
|
-
function mapFilePaths(_override) {
|
|
695
|
-
const override = {
|
|
696
|
-
..._override,
|
|
697
|
-
};
|
|
546
|
+
function mapFilePaths(override) {
|
|
698
547
|
if (override.files) {
|
|
699
548
|
override.files = Array.isArray(override.files)
|
|
700
549
|
? override.files
|
|
@@ -707,7 +556,6 @@ function mapFilePaths(_override) {
|
|
|
707
556
|
: [override.excludedFiles];
|
|
708
557
|
override.excludedFiles = override.excludedFiles.map((file) => (0, path_utils_1.mapFilePath)(file));
|
|
709
558
|
}
|
|
710
|
-
return override;
|
|
711
559
|
}
|
|
712
560
|
function addTSObjectProperty(elements, key, value) {
|
|
713
561
|
if (value) {
|
|
@@ -717,16 +565,18 @@ function addTSObjectProperty(elements, key, value) {
|
|
|
717
565
|
/**
|
|
718
566
|
* Generates an AST from a JSON-type input
|
|
719
567
|
*/
|
|
720
|
-
function generateAst(input
|
|
568
|
+
function generateAst(input) {
|
|
721
569
|
if (Array.isArray(input)) {
|
|
722
|
-
return ts.factory.createArrayLiteralExpression(input.map((item) => generateAst(item
|
|
570
|
+
return ts.factory.createArrayLiteralExpression(input.map((item) => generateAst(item)), input.length > 1 // multiline only if more than one item
|
|
723
571
|
);
|
|
724
572
|
}
|
|
725
573
|
if (input === null) {
|
|
726
574
|
return ts.factory.createNull();
|
|
727
575
|
}
|
|
728
576
|
if (typeof input === 'object') {
|
|
729
|
-
return ts.factory.createObjectLiteralExpression(
|
|
577
|
+
return ts.factory.createObjectLiteralExpression(Object.entries(input)
|
|
578
|
+
.filter(([_, value]) => value !== undefined)
|
|
579
|
+
.map(([key, value]) => ts.factory.createPropertyAssignment(isValidKey(key) ? key : ts.factory.createStringLiteral(key), generateAst(value))), Object.keys(input).length > 1 // multiline only if more than one property
|
|
730
580
|
);
|
|
731
581
|
}
|
|
732
582
|
if (typeof input === 'string') {
|
|
@@ -741,20 +591,6 @@ function generateAst(input, propertyAssignmentReplacer) {
|
|
|
741
591
|
// since we are parsing JSON, this should never happen
|
|
742
592
|
throw new Error(`Unknown type: ${typeof input} `);
|
|
743
593
|
}
|
|
744
|
-
function generatePropertyAssignmentsFromObjectEntries(input, propertyAssignmentReplacer) {
|
|
745
|
-
return Object.entries(input)
|
|
746
|
-
.filter(([_, value]) => value !== undefined)
|
|
747
|
-
.map(([key, value]) => {
|
|
748
|
-
const original = ts.factory.createPropertyAssignment(isValidKey(key) ? key : ts.factory.createStringLiteral(key), generateAst(value, propertyAssignmentReplacer));
|
|
749
|
-
if (propertyAssignmentReplacer &&
|
|
750
|
-
(typeof propertyAssignmentReplacer.keyToMatch === 'string'
|
|
751
|
-
? key === propertyAssignmentReplacer.keyToMatch
|
|
752
|
-
: propertyAssignmentReplacer.keyToMatch.test(key))) {
|
|
753
|
-
return propertyAssignmentReplacer.replacer(original, key);
|
|
754
|
-
}
|
|
755
|
-
return original;
|
|
756
|
-
});
|
|
757
|
-
}
|
|
758
594
|
function isValidKey(key) {
|
|
759
595
|
return /^[a-zA-Z0-9_]+$/.test(key);
|
|
760
596
|
}
|
package/src/plugins/plugin.js
CHANGED
|
@@ -47,9 +47,7 @@ const internalCreateNodes = async (configFilePath, options, context, projectsCac
|
|
|
47
47
|
// dedupe and sort project roots by depth for more efficient traversal
|
|
48
48
|
const dedupedProjectRoots = Array.from(new Set(projectFiles.map((f) => (0, posix_1.dirname)(f)))).sort((a, b) => (a !== b && isSubDir(a, b) ? -1 : 1));
|
|
49
49
|
const excludePatterns = dedupedProjectRoots.map((root) => `${root}/**/*`);
|
|
50
|
-
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)(
|
|
51
|
-
useFlatConfigOverrideVal: (0, config_file_1.isFlatConfig)(configFilePath),
|
|
52
|
-
});
|
|
50
|
+
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)((0, config_file_1.isFlatConfig)(configFilePath));
|
|
53
51
|
const eslintVersion = ESLint.version;
|
|
54
52
|
const projects = {};
|
|
55
53
|
await Promise.all(dedupedProjectRoots.map(async (childProjectRoot, index) => {
|
|
@@ -98,9 +96,7 @@ const internalCreateNodes = async (configFilePath, options, context, projectsCac
|
|
|
98
96
|
};
|
|
99
97
|
const internalCreateNodesV2 = async (configFilePath, options, context, eslintConfigFiles, projectRootsByEslintRoots, lintableFilesPerProjectRoot, projectsCache) => {
|
|
100
98
|
const configDir = (0, posix_1.dirname)(configFilePath);
|
|
101
|
-
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)(
|
|
102
|
-
useFlatConfigOverrideVal: (0, config_file_1.isFlatConfig)(configFilePath),
|
|
103
|
-
});
|
|
99
|
+
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)((0, config_file_1.isFlatConfig)(configFilePath));
|
|
104
100
|
const eslintVersion = ESLint.version;
|
|
105
101
|
const projects = {};
|
|
106
102
|
await Promise.all(projectRootsByEslintRoots.get(configDir).map(async (projectRoot) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Tree } from '@nx/devkit';
|
|
2
2
|
export declare const eslintFlatConfigFilenames: string[];
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function useFlatConfig(tree
|
|
3
|
+
export declare function flatConfigEslintFilename(tree: Tree): string;
|
|
4
|
+
export declare function useFlatConfig(tree: Tree): boolean;
|
package/src/utils/flat-config.js
CHANGED
|
@@ -1,47 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.eslintFlatConfigFilenames = void 0;
|
|
4
|
-
exports.
|
|
4
|
+
exports.flatConfigEslintFilename = flatConfigEslintFilename;
|
|
5
5
|
exports.useFlatConfig = useFlatConfig;
|
|
6
|
-
const semver_1 = require("semver");
|
|
7
6
|
// todo: add support for eslint.config.mjs,
|
|
8
7
|
exports.eslintFlatConfigFilenames = [
|
|
9
8
|
'eslint.config.js',
|
|
10
9
|
'eslint.config.cjs',
|
|
11
10
|
];
|
|
12
|
-
function
|
|
11
|
+
function flatConfigEslintFilename(tree) {
|
|
13
12
|
for (const file of exports.eslintFlatConfigFilenames) {
|
|
14
13
|
if (tree.exists(file)) {
|
|
15
14
|
return file;
|
|
16
15
|
}
|
|
17
16
|
}
|
|
18
|
-
throw new Error('Could not find
|
|
17
|
+
throw new Error('Could not find flat config file');
|
|
19
18
|
}
|
|
20
19
|
function useFlatConfig(tree) {
|
|
21
|
-
// Prioritize taking ESLint's own environment variable into account when determining if we should use flat config
|
|
22
|
-
// If it is not defined, then default to true.
|
|
23
|
-
if (process.env.ESLINT_USE_FLAT_CONFIG === 'true') {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
else if (process.env.ESLINT_USE_FLAT_CONFIG === 'false') {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
// If we find an existing flat config file in the root of the provided tree, we should use flat config
|
|
30
|
-
if (tree) {
|
|
31
|
-
const hasRootFlatConfig = exports.eslintFlatConfigFilenames.some((filename) => tree.exists(filename));
|
|
32
|
-
if (hasRootFlatConfig) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
// Otherwise fallback to checking the installed eslint version
|
|
37
20
|
try {
|
|
38
|
-
|
|
39
|
-
// Default to any v8 version to compare against in this case as it implies a much older version of ESLint was found (and gte() requires a valid version)
|
|
40
|
-
const eslintVersion = ESLint.version || '8.0.0';
|
|
41
|
-
return (0, semver_1.gte)(eslintVersion, '9.0.0');
|
|
21
|
+
return !!flatConfigEslintFilename(tree);
|
|
42
22
|
}
|
|
43
23
|
catch {
|
|
44
|
-
|
|
45
|
-
return true;
|
|
24
|
+
return false;
|
|
46
25
|
}
|
|
47
26
|
}
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveESLintClass = resolveESLintClass;
|
|
4
|
-
|
|
5
|
-
async function resolveESLintClass(opts) {
|
|
4
|
+
async function resolveESLintClass(useFlatConfig = false) {
|
|
6
5
|
try {
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
// In eslint 8.57.0 (the final v8 version), a dedicated API was added for resolving the correct ESLint class.
|
|
7
|
+
const eslint = await Promise.resolve().then(() => require('eslint'));
|
|
8
|
+
if (typeof eslint.loadESLint === 'function') {
|
|
9
|
+
return await eslint.loadESLint({ useFlatConfig });
|
|
10
|
+
}
|
|
11
|
+
// If that API is not available (an older version of v8), we need to use the old way of resolving the ESLint class.
|
|
12
|
+
if (!useFlatConfig) {
|
|
13
|
+
return eslint.ESLint;
|
|
14
|
+
}
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
16
|
+
const { FlatESLint } = require('eslint/use-at-your-own-risk');
|
|
17
|
+
return FlatESLint;
|
|
15
18
|
}
|
|
16
19
|
catch {
|
|
17
|
-
throw new Error('Unable to find
|
|
20
|
+
throw new Error('Unable to find ESLint. Ensure ESLint is installed.');
|
|
18
21
|
}
|
|
19
22
|
}
|
package/src/utils/versions.d.ts
CHANGED
|
@@ -3,6 +3,3 @@ export declare const eslintVersion = "~8.57.0";
|
|
|
3
3
|
export declare const eslintrcVersion = "^2.1.1";
|
|
4
4
|
export declare const eslintConfigPrettierVersion = "^9.0.0";
|
|
5
5
|
export declare const typescriptESLintVersion = "^7.16.0";
|
|
6
|
-
export declare const eslint9__typescriptESLintVersion = "^8.0.0";
|
|
7
|
-
export declare const eslint9__eslintVersion = "^9.8.0";
|
|
8
|
-
export declare const eslintCompat = "^1.1.1";
|
package/src/utils/versions.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.typescriptESLintVersion = exports.eslintConfigPrettierVersion = exports.eslintrcVersion = exports.eslintVersion = exports.nxVersion = void 0;
|
|
4
4
|
exports.nxVersion = require('../../package.json').version;
|
|
5
5
|
exports.eslintVersion = '~8.57.0';
|
|
6
6
|
exports.eslintrcVersion = '^2.1.1';
|
|
7
7
|
exports.eslintConfigPrettierVersion = '^9.0.0';
|
|
8
8
|
exports.typescriptESLintVersion = '^7.16.0';
|
|
9
|
-
// Updated linting stack for ESLint v9, typescript-eslint v8
|
|
10
|
-
exports.eslint9__typescriptESLintVersion = '^8.0.0';
|
|
11
|
-
exports.eslint9__eslintVersion = '^9.8.0';
|
|
12
|
-
exports.eslintCompat = '^1.1.1';
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getInstalledEslintVersion = getInstalledEslintVersion;
|
|
4
|
-
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const semver_1 = require("@nx/devkit/src/utils/semver");
|
|
6
|
-
const devkit_internals_1 = require("nx/src/devkit-internals");
|
|
7
|
-
function getInstalledEslintVersion(tree) {
|
|
8
|
-
try {
|
|
9
|
-
const eslintPackageJson = (0, devkit_internals_1.readModulePackageJson)('eslint').packageJson;
|
|
10
|
-
return eslintPackageJson.version;
|
|
11
|
-
}
|
|
12
|
-
catch { }
|
|
13
|
-
// eslint is not installed on disk, it could be in the package.json
|
|
14
|
-
// but waiting to be installed
|
|
15
|
-
const rootPackageJson = tree
|
|
16
|
-
? (0, devkit_1.readJson)(tree, 'package.json')
|
|
17
|
-
: (0, devkit_1.readJsonFile)('package.json');
|
|
18
|
-
const eslintVersionInRootPackageJson = rootPackageJson.devDependencies?.['eslint'] ??
|
|
19
|
-
rootPackageJson.dependencies?.['eslint'];
|
|
20
|
-
if (!eslintVersionInRootPackageJson) {
|
|
21
|
-
// eslint is not installed
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
// try to parse and return the version
|
|
26
|
-
return (0, semver_1.checkAndCleanWithSemver)('eslint', eslintVersionInRootPackageJson);
|
|
27
|
-
}
|
|
28
|
-
catch { }
|
|
29
|
-
// we could not resolve the version
|
|
30
|
-
return null;
|
|
31
|
-
}
|