@angular-eslint/builder 21.4.1-alpha.8 → 22.0.1-alpha.0
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/README.md +0 -2
- package/dist/lint.impl.d.ts.map +1 -1
- package/dist/lint.impl.js +9 -32
- package/dist/schema.json +1 -27
- package/dist/utils/eslint-utils.d.ts +12 -2
- package/dist/utils/eslint-utils.d.ts.map +1 -1
- package/dist/utils/eslint-utils.js +47 -73
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -14,8 +14,6 @@ You can profile rule execution times by enabling ESLint's stats output:
|
|
|
14
14
|
ng lint --stats
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
This option requires a flat ESLint configuration (`eslint.config.js/ts/mjs`). Using `--stats` with legacy `.eslintrc.*` files will cause an error.
|
|
18
|
-
|
|
19
17
|
## Bulk suppressions
|
|
20
18
|
|
|
21
19
|
ESLint introduced bulk suppressions in v9.24. This allows you to enable new lint rules without having to fix every existing violation first. For details, see https://eslint.org/docs/latest/use/suppressions. In ESLint v10.1 a subset of the suppressions functionality was added to the Node.js API (https://eslint.org/blog/2026/03/eslint-v10.1.0-released/#api-support-for-bulk-suppressions).
|
package/dist/lint.impl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.impl.d.ts","sourceRoot":"","sources":["../src/lint.impl.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;;AAMvC,
|
|
1
|
+
{"version":3,"file":"lint.impl.d.ts","sourceRoot":"","sources":["../src/lint.impl.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;;AAMvC,wBA0NE"}
|
package/dist/lint.impl.js
CHANGED
|
@@ -38,20 +38,7 @@ exports.default = (0, architect_1.createBuilder)(async (options, context) => {
|
|
|
38
38
|
options.suppressionsLocation = options.suppressionsLocation
|
|
39
39
|
? (0, path_1.resolve)(systemRoot, options.suppressionsLocation)
|
|
40
40
|
: null;
|
|
41
|
-
|
|
42
|
-
* Until ESLint v9 is released and the new so called flat config is the default
|
|
43
|
-
* we only want to support it if the user has explicitly opted into it by converting
|
|
44
|
-
* their root ESLint config to use a supported flat config file name.
|
|
45
|
-
*/
|
|
46
|
-
const useFlatConfig = eslint_utils_1.supportedFlatConfigNames.some((name) => (0, fs_1.existsSync)((0, path_1.join)(systemRoot, name)));
|
|
47
|
-
const { eslint, ESLint } = await (0, eslint_utils_1.resolveAndInstantiateESLint)(eslintConfigPath, options, useFlatConfig);
|
|
48
|
-
const version = ESLint?.version?.split('.');
|
|
49
|
-
if (!version ||
|
|
50
|
-
version.length < 2 ||
|
|
51
|
-
Number(version[0]) < 7 ||
|
|
52
|
-
(Number(version[0]) === 7 && Number(version[1]) < 6)) {
|
|
53
|
-
throw new Error('ESLint must be version 7.6 or higher.');
|
|
54
|
-
}
|
|
41
|
+
const { eslint, ESLint } = await (0, eslint_utils_1.resolveAndInstantiateESLint)(eslintConfigPath, options);
|
|
55
42
|
let lintResults = [];
|
|
56
43
|
try {
|
|
57
44
|
lintResults = await eslint.lintFiles(options.lintFilePatterns);
|
|
@@ -65,9 +52,9 @@ exports.default = (0, architect_1.createBuilder)(async (options, context) => {
|
|
|
65
52
|
resolveESLintConfigPath(projectRoot) ?? '';
|
|
66
53
|
}
|
|
67
54
|
console.error(`
|
|
68
|
-
Error: You have attempted to use a lint rule which requires the full TypeScript type-checker to be available, but you
|
|
55
|
+
Error: You have attempted to use a lint rule which requires the full TypeScript type-checker to be available, but you have not configured type information for the TypeScript files in your project ESLint config ${eslintConfigPath || eslintConfigPathForError}
|
|
69
56
|
|
|
70
|
-
For full guidance on how to resolve this issue, please see https://github.com/angular-eslint/angular-eslint/blob/main/docs/RULES_REQUIRING_TYPE_INFORMATION.md
|
|
57
|
+
The simplest way to enable type information is to set \`languageOptions.parserOptions.projectService\` to \`true\` for your TypeScript files. For full guidance on how to resolve this issue, please see https://github.com/angular-eslint/angular-eslint/blob/main/docs/RULES_REQUIRING_TYPE_INFORMATION.md
|
|
71
58
|
`);
|
|
72
59
|
return {
|
|
73
60
|
success: false,
|
|
@@ -81,7 +68,7 @@ For full guidance on how to resolve this issue, please see https://github.com/an
|
|
|
81
68
|
.filter((pattern) => !!pattern)
|
|
82
69
|
.map((pattern) => `- '${pattern}'`);
|
|
83
70
|
if (ignoredPatterns.length) {
|
|
84
|
-
throw new Error(`All files matching the following patterns are ignored:\n${ignoredPatterns.join('\n')}\n\nPlease check
|
|
71
|
+
throw new Error(`All files matching the following patterns are ignored:\n${ignoredPatterns.join('\n')}\n\nPlease check the 'ignores' configuration in your ESLint flat config.`);
|
|
85
72
|
}
|
|
86
73
|
throw new Error('Invalid lint configuration. Nothing to lint. Please check your lint target pattern(s).');
|
|
87
74
|
}
|
|
@@ -173,21 +160,11 @@ For full guidance on how to resolve this issue, please see https://github.com/an
|
|
|
173
160
|
}
|
|
174
161
|
});
|
|
175
162
|
function resolveESLintConfigPath(projectRoot) {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if ((0, fs_1.existsSync)(jsPath)) {
|
|
182
|
-
return jsPath;
|
|
183
|
-
}
|
|
184
|
-
const mjsPath = (0, path_1.join)(projectRoot, 'eslint.config.mjs');
|
|
185
|
-
if ((0, fs_1.existsSync)(mjsPath)) {
|
|
186
|
-
return mjsPath;
|
|
187
|
-
}
|
|
188
|
-
const cjsPath = (0, path_1.join)(projectRoot, 'eslint.config.cjs');
|
|
189
|
-
if ((0, fs_1.existsSync)(cjsPath)) {
|
|
190
|
-
return cjsPath;
|
|
163
|
+
for (const name of eslint_utils_1.defaultFlatConfigNames) {
|
|
164
|
+
const candidate = (0, path_1.join)(projectRoot, name);
|
|
165
|
+
if ((0, fs_1.existsSync)(candidate)) {
|
|
166
|
+
return candidate;
|
|
167
|
+
}
|
|
191
168
|
}
|
|
192
169
|
return null;
|
|
193
170
|
}
|
package/dist/schema.json
CHANGED
|
@@ -90,37 +90,11 @@
|
|
|
90
90
|
{ "minLength": 1 }
|
|
91
91
|
]
|
|
92
92
|
},
|
|
93
|
-
"ignorePath": {
|
|
94
|
-
"type": "string",
|
|
95
|
-
"description": "The path of the `.eslintignore` file."
|
|
96
|
-
},
|
|
97
|
-
"noEslintrc": {
|
|
98
|
-
"type": "boolean",
|
|
99
|
-
"description": "NOTE: eslintrc config only. The equivalent of the `--no-eslintrc` flag on the ESLint CLI, it is false by default",
|
|
100
|
-
"default": false
|
|
101
|
-
},
|
|
102
93
|
"noConfigLookup": {
|
|
103
94
|
"type": "boolean",
|
|
104
|
-
"description": "
|
|
95
|
+
"description": "The equivalent of the `--no-config-lookup` flag on the ESLint CLI, it is false by default",
|
|
105
96
|
"default": false
|
|
106
97
|
},
|
|
107
|
-
"rulesdir": {
|
|
108
|
-
"type": "array",
|
|
109
|
-
"description": "The equivalent of the `--rulesdir` flag on the ESLint CLI, it is an empty array by default",
|
|
110
|
-
"default": [],
|
|
111
|
-
"items": {
|
|
112
|
-
"type": "string"
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
"resolvePluginsRelativeTo": {
|
|
116
|
-
"type": "string",
|
|
117
|
-
"description": "The equivalent of the `--resolve-plugins-relative-to` flag on the ESLint CLI"
|
|
118
|
-
},
|
|
119
|
-
"reportUnusedDisableDirectives": {
|
|
120
|
-
"type": "string",
|
|
121
|
-
"enum": ["off", "warn", "error"],
|
|
122
|
-
"description": "The equivalent of the `--report-unused-disable-directives` flag on the ESLint CLI."
|
|
123
|
-
},
|
|
124
98
|
"concurrency": {
|
|
125
99
|
"oneOf": [
|
|
126
100
|
{ "type": "string", "enum": ["auto", "off"] },
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { ESLint } from 'eslint';
|
|
2
2
|
import type { Schema } from '../schema';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* The conventional flat config file names that ESLint resolves automatically.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: this is NOT a restriction on what an explicitly provided config file may
|
|
7
|
+
* be named. ESLint's own `--config`/`overrideConfigFile` accepts a flat config
|
|
8
|
+
* file with any name, and so does this builder (see the legacy eslintrc denylist
|
|
9
|
+
* below). This list only mirrors the names ESLint discovers on its own when no
|
|
10
|
+
* explicit config is given, so we can reconstruct a likely config path for
|
|
11
|
+
* diagnostic messages.
|
|
12
|
+
*/
|
|
13
|
+
export declare const defaultFlatConfigNames: string[];
|
|
14
|
+
export declare function resolveAndInstantiateESLint(eslintConfigPath: string | undefined, options: Schema): Promise<{
|
|
5
15
|
ESLint: typeof import("eslint").ESLint;
|
|
6
16
|
eslint: ESLint;
|
|
7
17
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-utils.d.ts","sourceRoot":"","sources":["../../src/utils/eslint-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"eslint-utils.d.ts","sourceRoot":"","sources":["../../src/utils/eslint-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,UAOlC,CAAC;AAyCF,wBAAsB,2BAA2B,CAC/C,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,OAAO,EAAE,MAAM;;;GAqEhB"}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.defaultFlatConfigNames = void 0;
|
|
4
4
|
exports.resolveAndInstantiateESLint = resolveAndInstantiateESLint;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The conventional flat config file names that ESLint resolves automatically.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: this is NOT a restriction on what an explicitly provided config file may
|
|
9
|
+
* be named. ESLint's own `--config`/`overrideConfigFile` accepts a flat config
|
|
10
|
+
* file with any name, and so does this builder (see the legacy eslintrc denylist
|
|
11
|
+
* below). This list only mirrors the names ESLint discovers on its own when no
|
|
12
|
+
* explicit config is given, so we can reconstruct a likely config path for
|
|
13
|
+
* diagnostic messages.
|
|
14
|
+
*/
|
|
15
|
+
exports.defaultFlatConfigNames = [
|
|
6
16
|
'eslint.config.js',
|
|
7
17
|
'eslint.config.mjs',
|
|
8
18
|
'eslint.config.cjs',
|
|
@@ -10,19 +20,22 @@ exports.supportedFlatConfigNames = [
|
|
|
10
20
|
'eslint.config.mts',
|
|
11
21
|
'eslint.config.cts',
|
|
12
22
|
];
|
|
13
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Legacy "eslintrc" config file names (e.g. `.eslintrc`, `.eslintrc.json`,
|
|
25
|
+
* `.eslintrc.js`, `.eslintrc.yml`). ESLint removed support for this format in
|
|
26
|
+
* v10 and angular-eslint no longer supports it.
|
|
27
|
+
*
|
|
28
|
+
* We detect these names explicitly so we can surface a helpful error message.
|
|
29
|
+
* Any other file name is passed straight through to ESLint - exactly like
|
|
30
|
+
* ESLint's own `--config`/`overrideConfigFile`, a flat config file can have
|
|
31
|
+
* any name, so we deliberately do NOT require the `eslint.config.*` naming
|
|
32
|
+
* convention for an explicitly provided config file.
|
|
33
|
+
*/
|
|
34
|
+
const legacyEslintrcConfigFilePattern = /(^|[\\/])\.eslintrc(\.(c?js|ya?ml|json))?$/;
|
|
35
|
+
async function resolveESLintClass() {
|
|
14
36
|
try {
|
|
15
|
-
// In eslint 8.57.0 (the final v8 minor version), a dedicated API was added for resolving the correct ESLint class.
|
|
16
37
|
const eslint = await import('eslint');
|
|
17
|
-
|
|
18
|
-
return await eslint.loadESLint({ useFlatConfig });
|
|
19
|
-
}
|
|
20
|
-
// If that API is not available (an older version of v8), we need to use the old way of resolving the ESLint class.
|
|
21
|
-
if (!useFlatConfig) {
|
|
22
|
-
return eslint.ESLint;
|
|
23
|
-
}
|
|
24
|
-
const { FlatESLint } = (await import('eslint/use-at-your-own-risk'));
|
|
25
|
-
return FlatESLint;
|
|
38
|
+
return eslint.ESLint;
|
|
26
39
|
}
|
|
27
40
|
catch {
|
|
28
41
|
throw new Error('Unable to find ESLint. Ensure ESLint is installed.');
|
|
@@ -39,22 +52,12 @@ function validateConcurrency(concurrency) {
|
|
|
39
52
|
}
|
|
40
53
|
throw new Error('The --concurrency option must be auto, off or a positive integer');
|
|
41
54
|
}
|
|
42
|
-
async function resolveAndInstantiateESLint(eslintConfigPath, options
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (options.applySuppressions && !useFlatConfig) {
|
|
47
|
-
throw new Error('The --apply-suppressions option requires ESLint Flat Config');
|
|
48
|
-
}
|
|
49
|
-
if (options.suppressionsLocation && !useFlatConfig) {
|
|
50
|
-
throw new Error('The --suppressions-location option requires ESLint Flat Config');
|
|
51
|
-
}
|
|
52
|
-
if (useFlatConfig &&
|
|
53
|
-
eslintConfigPath &&
|
|
54
|
-
!exports.supportedFlatConfigNames.some((name) => eslintConfigPath.endsWith(name))) {
|
|
55
|
-
throw new Error(`When using the new Flat Config with ESLint, all configs must be named ${exports.supportedFlatConfigNames.join(' or ')}, and .eslintrc files may not be used. See https://eslint.org/docs/latest/use/configure/configuration-files`);
|
|
55
|
+
async function resolveAndInstantiateESLint(eslintConfigPath, options) {
|
|
56
|
+
if (eslintConfigPath &&
|
|
57
|
+
legacyEslintrcConfigFilePattern.test(eslintConfigPath)) {
|
|
58
|
+
throw new Error(`The ESLint config file "${eslintConfigPath}" uses the legacy "eslintrc" format, which is no longer supported. Please use an ESLint flat config file (it can have any name, e.g. eslint.config.js). See https://eslint.org/docs/latest/use/configure/configuration-files`);
|
|
56
59
|
}
|
|
57
|
-
const ESLint = await resolveESLintClass(
|
|
60
|
+
const ESLint = await resolveESLintClass();
|
|
58
61
|
const eslintOptions = {
|
|
59
62
|
fix: !!options.fix,
|
|
60
63
|
cache: !!options.cache,
|
|
@@ -77,55 +80,26 @@ async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatCon
|
|
|
77
80
|
validateConcurrency(concurrency);
|
|
78
81
|
eslintOptions.concurrency = concurrency;
|
|
79
82
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
throw new Error('For Flat Config, ESLint removed `ignorePath` and so it is not supported as an option. See https://eslint.org/docs/latest/use/configure/configuration-files-new');
|
|
96
|
-
}
|
|
97
|
-
if (options.reportUnusedDisableDirectives) {
|
|
98
|
-
throw new Error('For Flat Config, ESLint removed `reportUnusedDisableDirectives` and so it is not supported as an option. See https://eslint.org/docs/latest/use/configure/configuration-files-new');
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Adapted from https://github.com/eslint/eslint/blob/50f03a119e6827c03b1d6c86d3aa1f4820b609e8/lib/cli.js#L144
|
|
102
|
-
*/
|
|
103
|
-
if (typeof options.noConfigLookup !== 'undefined') {
|
|
104
|
-
const configLookup = !options.noConfigLookup;
|
|
105
|
-
let overrideConfigFile = typeof eslintConfigPath === 'string' ? eslintConfigPath : !configLookup;
|
|
106
|
-
if (overrideConfigFile === false) {
|
|
107
|
-
overrideConfigFile = undefined;
|
|
108
|
-
}
|
|
109
|
-
eslintOptions.overrideConfigFile = overrideConfigFile;
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
eslintOptions.overrideConfigFile = eslintConfigPath;
|
|
83
|
+
eslintOptions.stats = !!options.stats;
|
|
84
|
+
if (options.applySuppressions) {
|
|
85
|
+
eslintOptions.applySuppressions = true;
|
|
86
|
+
}
|
|
87
|
+
if (options.suppressionsLocation) {
|
|
88
|
+
eslintOptions.suppressionsLocation = options.suppressionsLocation;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Adapted from https://github.com/eslint/eslint/blob/50f03a119e6827c03b1d6c86d3aa1f4820b609e8/lib/cli.js#L144
|
|
92
|
+
*/
|
|
93
|
+
if (typeof options.noConfigLookup !== 'undefined') {
|
|
94
|
+
const configLookup = !options.noConfigLookup;
|
|
95
|
+
let overrideConfigFile = typeof eslintConfigPath === 'string' ? eslintConfigPath : !configLookup;
|
|
96
|
+
if (overrideConfigFile === false) {
|
|
97
|
+
overrideConfigFile = undefined;
|
|
113
98
|
}
|
|
99
|
+
eslintOptions.overrideConfigFile = overrideConfigFile;
|
|
114
100
|
}
|
|
115
101
|
else {
|
|
116
102
|
eslintOptions.overrideConfigFile = eslintConfigPath;
|
|
117
|
-
const legacyOptions = eslintOptions;
|
|
118
|
-
legacyOptions.rulePaths = options.rulesdir || [];
|
|
119
|
-
legacyOptions.resolvePluginsRelativeTo =
|
|
120
|
-
options.resolvePluginsRelativeTo || undefined;
|
|
121
|
-
legacyOptions.ignorePath = options.ignorePath || undefined;
|
|
122
|
-
/**
|
|
123
|
-
* If "noEslintrc" is set to `true` (and therefore here "useEslintrc" will be `false`), then ESLint will not
|
|
124
|
-
* merge the provided config with others it finds automatically.
|
|
125
|
-
*/
|
|
126
|
-
legacyOptions.useEslintrc = !options.noEslintrc;
|
|
127
|
-
legacyOptions.reportUnusedDisableDirectives =
|
|
128
|
-
options.reportUnusedDisableDirectives || undefined;
|
|
129
103
|
}
|
|
130
104
|
const eslint = new ESLint(eslintOptions);
|
|
131
105
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-eslint/builder",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.0.1-alpha.0",
|
|
4
4
|
"description": "Angular CLI builder for ESLint",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
"builders.json"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@angular-devkit/architect": ">= 0.
|
|
23
|
-
"@angular-devkit/core": ">=
|
|
22
|
+
"@angular-devkit/architect": ">= 0.2200.0 < 0.2300.0",
|
|
23
|
+
"@angular-devkit/core": ">= 22.0.0 < 23.0.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@angular/cli": ">=
|
|
27
|
-
"eslint": "^
|
|
26
|
+
"@angular/cli": ">= 22.0.0 < 23.0.0",
|
|
27
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
28
28
|
"typescript": "*"
|
|
29
29
|
},
|
|
30
30
|
"builders": "./builders.json",
|