@nx/eslint 0.0.0-pr-27404-00130f5 → 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 +14 -9
- 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 +44 -203
- 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,19 +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
89
|
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(moduleBoundariesOverride));
|
|
90
90
|
}
|
|
91
|
-
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateFlatOverride)(
|
|
92
|
-
|
|
93
|
-
|
|
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));
|
|
95
|
+
}
|
|
96
|
+
// add ignore for .nx folder
|
|
97
|
+
content = (0, ast_utils_1.addBlockToFlatConfigExport)(content, (0, ast_utils_1.generateAst)({
|
|
98
|
+
ignores: ['.nx'],
|
|
94
99
|
}));
|
|
95
100
|
return content;
|
|
96
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: ['**/*/*eslint*'],
|
|
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
|
*/
|
|
@@ -439,45 +404,13 @@ function removeCompatExtends(content, compatExtends) {
|
|
|
439
404
|
type: devkit_1.ChangeType.Insert,
|
|
440
405
|
index: node.pos,
|
|
441
406
|
text: '\n' +
|
|
442
|
-
body.replace(new RegExp('[ \t]s*...' + paramName + '
|
|
407
|
+
body.replace(new RegExp('[ \t]s*...' + paramName + '[ \t]*,?\\s*', 'g'), ''),
|
|
443
408
|
});
|
|
444
409
|
}
|
|
445
410
|
}
|
|
446
411
|
});
|
|
447
412
|
return (0, devkit_1.applyChangesToString)(content, changes);
|
|
448
413
|
}
|
|
449
|
-
function removePredefinedConfigs(content, moduleImport, moduleVariable, configs) {
|
|
450
|
-
const source = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
|
451
|
-
const changes = [];
|
|
452
|
-
let removeImport = true;
|
|
453
|
-
findAllBlocks(source).forEach((node) => {
|
|
454
|
-
if (ts.isSpreadElement(node) &&
|
|
455
|
-
ts.isElementAccessExpression(node.expression) &&
|
|
456
|
-
ts.isPropertyAccessExpression(node.expression.expression) &&
|
|
457
|
-
ts.isIdentifier(node.expression.expression.expression) &&
|
|
458
|
-
node.expression.expression.expression.getText() === moduleVariable &&
|
|
459
|
-
ts.isStringLiteral(node.expression.argumentExpression)) {
|
|
460
|
-
const config = node.expression.argumentExpression.getText();
|
|
461
|
-
// Check the text without quotes
|
|
462
|
-
if (configs.includes(config.substring(1, config.length - 1))) {
|
|
463
|
-
changes.push({
|
|
464
|
-
type: devkit_1.ChangeType.Delete,
|
|
465
|
-
start: node.pos,
|
|
466
|
-
length: node.end - node.pos + 1, // trailing comma
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
// If there is still a config used, do not remove import
|
|
471
|
-
removeImport = false;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
let updated = (0, devkit_1.applyChangesToString)(content, changes);
|
|
476
|
-
if (removeImport) {
|
|
477
|
-
updated = removeImportFromFlatConfig(updated, moduleVariable, moduleImport);
|
|
478
|
-
}
|
|
479
|
-
return updated;
|
|
480
|
-
}
|
|
481
414
|
/**
|
|
482
415
|
* Add plugins block to the top of the export blocks
|
|
483
416
|
*/
|
|
@@ -494,7 +427,7 @@ function addPluginsToExportsBlock(content, plugins) {
|
|
|
494
427
|
/**
|
|
495
428
|
* Adds compat if missing to flat config
|
|
496
429
|
*/
|
|
497
|
-
function
|
|
430
|
+
function addCompatToFlatConfig(content) {
|
|
498
431
|
let result = content;
|
|
499
432
|
result = addImportToFlatConfig(result, 'js', '@eslint/js');
|
|
500
433
|
if (result.includes('const compat = new FlatCompat')) {
|
|
@@ -506,21 +439,28 @@ function addFlatCompatToFlatConfig(content) {
|
|
|
506
439
|
{
|
|
507
440
|
type: devkit_1.ChangeType.Insert,
|
|
508
441
|
index: index - 1,
|
|
509
|
-
text:
|
|
510
|
-
const compat = new FlatCompat({
|
|
511
|
-
baseDirectory: __dirname,
|
|
512
|
-
recommendedConfig: js.configs.recommended,
|
|
513
|
-
});
|
|
514
|
-
`,
|
|
442
|
+
text: `${DEFAULT_FLAT_CONFIG}\n`,
|
|
515
443
|
},
|
|
516
444
|
]);
|
|
517
445
|
}
|
|
446
|
+
const DEFAULT_FLAT_CONFIG = `
|
|
447
|
+
const compat = new FlatCompat({
|
|
448
|
+
baseDirectory: __dirname,
|
|
449
|
+
recommendedConfig: js.configs.recommended,
|
|
450
|
+
});
|
|
451
|
+
`;
|
|
518
452
|
/**
|
|
519
453
|
* Generate node list representing the imports and the exports blocks
|
|
520
454
|
* Optionally add flat compat initialization
|
|
521
455
|
*/
|
|
522
|
-
function createNodeList(importsMap, exportElements) {
|
|
456
|
+
function createNodeList(importsMap, exportElements, isFlatCompatNeeded) {
|
|
523
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
|
+
}
|
|
524
464
|
// generateRequire(varName, imp, ts.factory);
|
|
525
465
|
Array.from(importsMap.entries()).forEach(([imp, varName]) => {
|
|
526
466
|
importsList.push(generateRequire(varName, imp));
|
|
@@ -528,7 +468,7 @@ function createNodeList(importsMap, exportElements) {
|
|
|
528
468
|
return ts.factory.createNodeArray([
|
|
529
469
|
// add plugin imports
|
|
530
470
|
...importsList,
|
|
531
|
-
ts.createSourceFile('', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.JS),
|
|
471
|
+
ts.createSourceFile('', isFlatCompatNeeded ? DEFAULT_FLAT_CONFIG : '', ts.ScriptTarget.Latest, false, ts.ScriptKind.JS),
|
|
532
472
|
// creates:
|
|
533
473
|
// module.exports = [ ... ];
|
|
534
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))),
|
|
@@ -540,11 +480,6 @@ function generateSpreadElement(name) {
|
|
|
540
480
|
function generatePluginExtendsElement(plugins) {
|
|
541
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))));
|
|
542
482
|
}
|
|
543
|
-
function generatePluginExtendsElementWithCompatFixup(plugin) {
|
|
544
|
-
return ts.factory.createSpreadElement(ts.factory.createCallExpression(ts.factory.createIdentifier('fixupConfigRules'), undefined, [
|
|
545
|
-
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('compat'), ts.factory.createIdentifier('extends')), undefined, [ts.factory.createStringLiteral(plugin)]),
|
|
546
|
-
]));
|
|
547
|
-
}
|
|
548
483
|
/**
|
|
549
484
|
* Stringifies TS nodes to file content string
|
|
550
485
|
*/
|
|
@@ -567,95 +502,21 @@ function generateRequire(variableName, imp) {
|
|
|
567
502
|
], ts.NodeFlags.Const));
|
|
568
503
|
}
|
|
569
504
|
/**
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
* Converts a glob pattern to a format that can be used in a flat config.
|
|
573
|
-
* @param {string} pattern The glob pattern to convert.
|
|
574
|
-
* @returns {string} The converted glob pattern.
|
|
575
|
-
*/
|
|
576
|
-
function convertGlobPattern(pattern) {
|
|
577
|
-
const isNegated = pattern.startsWith('!');
|
|
578
|
-
const patternToTest = isNegated ? pattern.slice(1) : pattern;
|
|
579
|
-
// if the pattern is already in the correct format, return it
|
|
580
|
-
if (patternToTest === '**' || patternToTest.includes('/')) {
|
|
581
|
-
return pattern;
|
|
582
|
-
}
|
|
583
|
-
return `${isNegated ? '!' : ''}**/${patternToTest}`;
|
|
584
|
-
}
|
|
585
|
-
// FROM: https://github.com/eslint/rewrite/blob/e2a7ec809db20e638abbad250d105ddbde88a8d5/packages/migrate-config/src/migrate-config.js#L38
|
|
586
|
-
const keysToCopy = ['settings', 'rules', 'processor'];
|
|
587
|
-
function overrideNeedsCompat(override) {
|
|
588
|
-
return override.env || override.extends || override.plugins;
|
|
589
|
-
}
|
|
590
|
-
/**
|
|
591
|
-
* Generates an AST object or spread element representing a modern flat config entry,
|
|
592
|
-
* based on a given legacy eslintrc JSON override object
|
|
505
|
+
* Generates AST object or spread element based on JSON override object
|
|
593
506
|
*/
|
|
594
|
-
function generateFlatOverride(
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
if (
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
const flatConfigOverride = {
|
|
604
|
-
files,
|
|
605
|
-
};
|
|
606
|
-
if (override.rules) {
|
|
607
|
-
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 } });
|
|
608
516
|
}
|
|
609
|
-
|
|
610
|
-
keysToCopy.forEach((key) => {
|
|
611
|
-
if (override[key]) {
|
|
612
|
-
flatConfigOverride[key] = override[key];
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
if (override.parser || override.parserOptions) {
|
|
616
|
-
const languageOptions = {};
|
|
617
|
-
if (override.parser) {
|
|
618
|
-
languageOptions['parser'] = override.parser;
|
|
619
|
-
}
|
|
620
|
-
if (override.parserOptions) {
|
|
621
|
-
languageOptions['parserOptions'] = override.parserOptions;
|
|
622
|
-
}
|
|
623
|
-
if (Object.keys(languageOptions).length) {
|
|
624
|
-
flatConfigOverride.languageOptions = languageOptions;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
if (override['languageOptions']) {
|
|
628
|
-
flatConfigOverride.languageOptions = override['languageOptions'];
|
|
629
|
-
}
|
|
630
|
-
if (override.excludedFiles) {
|
|
631
|
-
flatConfigOverride.ignores = (Array.isArray(override.excludedFiles)
|
|
632
|
-
? override.excludedFiles
|
|
633
|
-
: [override.excludedFiles]).map((p) => convertGlobPattern(p));
|
|
634
|
-
}
|
|
635
|
-
return generateAst(flatConfigOverride, {
|
|
636
|
-
keyToMatch: /^(parser|rules)$/,
|
|
637
|
-
replacer: (propertyAssignment, propertyName) => {
|
|
638
|
-
if (propertyName === 'rules') {
|
|
639
|
-
// Add comment that user can override rules if there are no overrides.
|
|
640
|
-
if (ts.isObjectLiteralExpression(propertyAssignment.initializer) &&
|
|
641
|
-
propertyAssignment.initializer.properties.length === 0) {
|
|
642
|
-
return ts.addSyntheticLeadingComment(ts.factory.createPropertyAssignment(propertyAssignment.name, ts.factory.createObjectLiteralExpression([])), ts.SyntaxKind.SingleLineCommentTrivia, ' Override or add rules here');
|
|
643
|
-
}
|
|
644
|
-
return propertyAssignment;
|
|
645
|
-
}
|
|
646
|
-
else {
|
|
647
|
-
// Change parser to require statement.
|
|
648
|
-
return ts.factory.createPropertyAssignment('parser', ts.factory.createCallExpression(ts.factory.createIdentifier('require'), undefined, [
|
|
649
|
-
ts.factory.createStringLiteral(override['languageOptions']?.['parserOptions']?.parser ??
|
|
650
|
-
override['languageOptions']?.parser ??
|
|
651
|
-
override.parser),
|
|
652
|
-
]));
|
|
653
|
-
}
|
|
654
|
-
},
|
|
655
|
-
});
|
|
517
|
+
return generateAst(override);
|
|
656
518
|
}
|
|
657
|
-
|
|
658
|
-
const { excludedFiles, parser, parserOptions, rules, files, ...rest } = override;
|
|
519
|
+
const { files, excludedFiles, rules, parserOptions, ...rest } = override;
|
|
659
520
|
const objectLiteralElements = [
|
|
660
521
|
ts.factory.createSpreadAssignment(ts.factory.createIdentifier('config')),
|
|
661
522
|
];
|
|
@@ -682,14 +543,7 @@ function generateFlatOverride(_override) {
|
|
|
682
543
|
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createParenthesizedExpression(ts.factory.createObjectLiteralExpression(objectLiteralElements, true))),
|
|
683
544
|
]));
|
|
684
545
|
}
|
|
685
|
-
function
|
|
686
|
-
const node = ts.factory.createElementAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(moduleName), ts.factory.createIdentifier('configs')), ts.factory.createStringLiteral(predefinedConfigName));
|
|
687
|
-
return spread ? ts.factory.createSpreadElement(node) : node;
|
|
688
|
-
}
|
|
689
|
-
function mapFilePaths(_override) {
|
|
690
|
-
const override = {
|
|
691
|
-
..._override,
|
|
692
|
-
};
|
|
546
|
+
function mapFilePaths(override) {
|
|
693
547
|
if (override.files) {
|
|
694
548
|
override.files = Array.isArray(override.files)
|
|
695
549
|
? override.files
|
|
@@ -702,7 +556,6 @@ function mapFilePaths(_override) {
|
|
|
702
556
|
: [override.excludedFiles];
|
|
703
557
|
override.excludedFiles = override.excludedFiles.map((file) => (0, path_utils_1.mapFilePath)(file));
|
|
704
558
|
}
|
|
705
|
-
return override;
|
|
706
559
|
}
|
|
707
560
|
function addTSObjectProperty(elements, key, value) {
|
|
708
561
|
if (value) {
|
|
@@ -712,16 +565,18 @@ function addTSObjectProperty(elements, key, value) {
|
|
|
712
565
|
/**
|
|
713
566
|
* Generates an AST from a JSON-type input
|
|
714
567
|
*/
|
|
715
|
-
function generateAst(input
|
|
568
|
+
function generateAst(input) {
|
|
716
569
|
if (Array.isArray(input)) {
|
|
717
|
-
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
|
|
718
571
|
);
|
|
719
572
|
}
|
|
720
573
|
if (input === null) {
|
|
721
574
|
return ts.factory.createNull();
|
|
722
575
|
}
|
|
723
576
|
if (typeof input === 'object') {
|
|
724
|
-
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
|
|
725
580
|
);
|
|
726
581
|
}
|
|
727
582
|
if (typeof input === 'string') {
|
|
@@ -736,20 +591,6 @@ function generateAst(input, propertyAssignmentReplacer) {
|
|
|
736
591
|
// since we are parsing JSON, this should never happen
|
|
737
592
|
throw new Error(`Unknown type: ${typeof input} `);
|
|
738
593
|
}
|
|
739
|
-
function generatePropertyAssignmentsFromObjectEntries(input, propertyAssignmentReplacer) {
|
|
740
|
-
return Object.entries(input)
|
|
741
|
-
.filter(([_, value]) => value !== undefined)
|
|
742
|
-
.map(([key, value]) => {
|
|
743
|
-
const original = ts.factory.createPropertyAssignment(isValidKey(key) ? key : ts.factory.createStringLiteral(key), generateAst(value, propertyAssignmentReplacer));
|
|
744
|
-
if (propertyAssignmentReplacer &&
|
|
745
|
-
(typeof propertyAssignmentReplacer.keyToMatch === 'string'
|
|
746
|
-
? key === propertyAssignmentReplacer.keyToMatch
|
|
747
|
-
: propertyAssignmentReplacer.keyToMatch.test(key))) {
|
|
748
|
-
return propertyAssignmentReplacer.replacer(original, key);
|
|
749
|
-
}
|
|
750
|
-
return original;
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
594
|
function isValidKey(key) {
|
|
754
595
|
return /^[a-zA-Z0-9_]+$/.test(key);
|
|
755
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
|
-
}
|