@nx/eslint 22.3.3 → 22.4.0-beta.1
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/schema.d.ts +3 -0
- package/src/executors/lint/schema.json +18 -0
- package/src/executors/lint/utility/eslint-utils.d.ts.map +1 -1
- package/src/executors/lint/utility/eslint-utils.js +30 -1
- package/src/generators/utils/flat-config/ast-utils.d.ts +2 -1
- package/src/generators/utils/flat-config/ast-utils.d.ts.map +1 -1
- package/src/generators/utils/flat-config/ast-utils.js +107 -37
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/eslint",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.4.0-beta.1",
|
|
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,14 +35,14 @@
|
|
|
35
35
|
"eslint": "^8.0.0 || ^9.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@nx/devkit": "22.
|
|
39
|
-
"@nx/js": "22.
|
|
38
|
+
"@nx/devkit": "22.4.0-beta.1",
|
|
39
|
+
"@nx/js": "22.4.0-beta.1",
|
|
40
40
|
"semver": "^7.6.3",
|
|
41
41
|
"tslib": "^2.3.0",
|
|
42
42
|
"typescript": "~5.9.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"nx": "22.
|
|
45
|
+
"nx": "22.4.0-beta.1"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"@zkochan/js-yaml": {
|
|
@@ -22,6 +22,9 @@ export interface Schema extends JsonObject {
|
|
|
22
22
|
reportUnusedDisableDirectives: Linter.StringSeverity | null;
|
|
23
23
|
printConfig?: string | null;
|
|
24
24
|
errorOnUnmatchedPattern?: boolean;
|
|
25
|
+
suppressAll?: boolean;
|
|
26
|
+
suppressRule?: string[];
|
|
27
|
+
suppressionsLocation?: string;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
type Formatter =
|
|
@@ -142,6 +142,24 @@
|
|
|
142
142
|
"type": "boolean",
|
|
143
143
|
"description": "When set to false, equivalent of the `--no-error-on-unmatched-pattern` flag on the ESLint CLI.",
|
|
144
144
|
"default": true
|
|
145
|
+
},
|
|
146
|
+
"suppressAll": {
|
|
147
|
+
"type": "boolean",
|
|
148
|
+
"description": "Suppress all existing violations. This is equivalent to the `--suppress-all` flag on the ESLint CLI. Requires ESLint v9.24.0 or higher.",
|
|
149
|
+
"default": false
|
|
150
|
+
},
|
|
151
|
+
"suppressRule": {
|
|
152
|
+
"type": "array",
|
|
153
|
+
"description": "Suppress violations for specific rules. This is equivalent to the `--suppress-rule` flag on the ESLint CLI. Requires ESLint v9.24.0 or higher.",
|
|
154
|
+
"default": [],
|
|
155
|
+
"items": {
|
|
156
|
+
"type": "string"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"suppressionsLocation": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"description": "Specify the location of the suppressions file. This is equivalent to the `--suppressions-location` flag on the ESLint CLI. Defaults to 'eslint-suppressions.json' in the project root. Requires ESLint v9.24.0 or higher.",
|
|
162
|
+
"x-completion-type": "file"
|
|
145
163
|
}
|
|
146
164
|
},
|
|
147
165
|
"examplesFile": "../../../docs/eslint-examples.md"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-utils.d.ts","sourceRoot":"","sources":["../../../../../../../packages/eslint/src/executors/lint/utility/eslint-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,wBAAsB,2BAA2B,CAC/C,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,OAAO,EAAE,MAAM,EACf,aAAa,UAAQ;;;
|
|
1
|
+
{"version":3,"file":"eslint-utils.d.ts","sourceRoot":"","sources":["../../../../../../../packages/eslint/src/executors/lint/utility/eslint-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,wBAAsB,2BAA2B,CAC/C,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,OAAO,EAAE,MAAM,EACf,aAAa,UAAQ;;;GAyHtB"}
|
|
@@ -13,7 +13,7 @@ async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatCon
|
|
|
13
13
|
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)({
|
|
14
14
|
useFlatConfigOverrideVal: useFlatConfig,
|
|
15
15
|
});
|
|
16
|
-
// ruleFilter exist only in eslint 9+, remove this type when eslint 8 support dropped
|
|
16
|
+
// ruleFilter, suppressAll, suppressRule, suppressionsLocation exist only in eslint 9+, remove this type when eslint 8 support dropped
|
|
17
17
|
const eslintOptions = {
|
|
18
18
|
overrideConfigFile: eslintConfigPath,
|
|
19
19
|
fix: !!options.fix &&
|
|
@@ -64,6 +64,35 @@ async function resolveAndInstantiateESLint(eslintConfigPath, options, useFlatCon
|
|
|
64
64
|
if (options.quiet && (0, semver_1.gte)(ESLint.version, '9.0.0')) {
|
|
65
65
|
eslintOptions.ruleFilter = (rule) => rule.severity === 2;
|
|
66
66
|
}
|
|
67
|
+
// Handle bulk suppression options (ESLint v9.24.0+)
|
|
68
|
+
try {
|
|
69
|
+
if (ESLint.version && (0, semver_1.gte)(ESLint.version, '9.24.0')) {
|
|
70
|
+
if (options.suppressAll) {
|
|
71
|
+
eslintOptions.suppressAll = true;
|
|
72
|
+
}
|
|
73
|
+
if (options.suppressRule && options.suppressRule.length > 0) {
|
|
74
|
+
eslintOptions.suppressRule = options.suppressRule;
|
|
75
|
+
}
|
|
76
|
+
if (options.suppressionsLocation) {
|
|
77
|
+
eslintOptions.suppressionsLocation = options.suppressionsLocation;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (options.suppressAll ||
|
|
81
|
+
(options.suppressRule && options.suppressRule.length > 0) ||
|
|
82
|
+
options.suppressionsLocation) {
|
|
83
|
+
throw new Error('Bulk suppression options (suppressAll, suppressRule, suppressionsLocation) require ESLint v9.24.0 or higher. Current version: ' +
|
|
84
|
+
(ESLint.version || 'unknown'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// If version checking fails (e.g., in tests), skip suppression options
|
|
89
|
+
if (options.suppressAll ||
|
|
90
|
+
(options.suppressRule && options.suppressRule.length > 0) ||
|
|
91
|
+
options.suppressionsLocation) {
|
|
92
|
+
// In test environment, just skip the suppression options
|
|
93
|
+
console.warn('Bulk suppression options skipped due to version check failure');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
67
96
|
const eslint = new ESLint(eslintOptions);
|
|
68
97
|
return {
|
|
69
98
|
ESLint,
|
|
@@ -8,7 +8,8 @@ export declare function addPatternsToFlatConfigIgnoresBlock(content: string, ign
|
|
|
8
8
|
export declare function hasFlatConfigIgnoresBlock(content: string): boolean;
|
|
9
9
|
export declare function hasOverride(content: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean): boolean;
|
|
10
10
|
/**
|
|
11
|
-
* Finds an override matching the lookup function and applies the update function to it
|
|
11
|
+
* Finds an override matching the lookup function and applies the update function to it.
|
|
12
|
+
* Uses property-level AST updates to preserve properties with variable references.
|
|
12
13
|
*/
|
|
13
14
|
export declare function replaceOverride(content: string, root: string, lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean, update?: (override: Partial<Linter.ConfigOverride<Linter.RulesRecord>>) => Partial<Linter.ConfigOverride<Linter.RulesRecord>>): string;
|
|
14
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.d.ts","sourceRoot":"","sources":["../../../../../../../packages/eslint/src/generators/utils/flat-config/ast-utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AASjC;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA+BrE;AA2BD,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EAAE,GACvB,MAAM,CA0CR;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgBlE;AA8BD,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,OAAO,GACvE,OAAO,CAoCT;
|
|
1
|
+
{"version":3,"file":"ast-utils.d.ts","sourceRoot":"","sources":["../../../../../../../packages/eslint/src/generators/utils/flat-config/ast-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -245,7 +245,52 @@ function extractPropertiesFromObjectLiteral(node) {
|
|
|
245
245
|
return result;
|
|
246
246
|
}
|
|
247
247
|
/**
|
|
248
|
-
*
|
|
248
|
+
* Find a property assignment node by name in an object literal.
|
|
249
|
+
*/
|
|
250
|
+
function findPropertyNode(node, propertyName) {
|
|
251
|
+
for (const prop of node.properties) {
|
|
252
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
253
|
+
const name = prop.name.getText().replace(/['"]/g, '');
|
|
254
|
+
if (name === propertyName) {
|
|
255
|
+
return prop;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Find properties that are added, changed, or removed.
|
|
263
|
+
*/
|
|
264
|
+
function findChangedProperties(original, updated) {
|
|
265
|
+
const changed = [];
|
|
266
|
+
// Check modified/added properties
|
|
267
|
+
for (const key of Object.keys(updated)) {
|
|
268
|
+
if (JSON.stringify(original[key]) !== JSON.stringify(updated[key])) {
|
|
269
|
+
changed.push(key);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Check removed properties
|
|
273
|
+
for (const key of Object.keys(original)) {
|
|
274
|
+
if (!(key in updated)) {
|
|
275
|
+
changed.push(key);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return changed;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Serialize a value to JavaScript source code. Handles converting eslintrc parser format to flat config format.
|
|
282
|
+
*/
|
|
283
|
+
function serializeValue(value, format) {
|
|
284
|
+
const parserReplacement = format === 'mjs'
|
|
285
|
+
? (parser) => `(await import('${parser}'))`
|
|
286
|
+
: (parser) => `require('${parser}')`;
|
|
287
|
+
return JSON.stringify(value, null, 2)
|
|
288
|
+
.replace(/"parser": "([^"]+)"/g, (_, parser) => `"parser": ${parserReplacement(parser)}`)
|
|
289
|
+
.replaceAll(/\n/g, '\n '); // Maintain indentation
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Finds an override matching the lookup function and applies the update function to it.
|
|
293
|
+
* Uses property-level AST updates to preserve properties with variable references.
|
|
249
294
|
*/
|
|
250
295
|
function replaceOverride(content, root, lookup, update) {
|
|
251
296
|
const source = ts.createSourceFile('', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
|
@@ -256,45 +301,70 @@ function replaceOverride(content, root, lookup, update) {
|
|
|
256
301
|
}
|
|
257
302
|
const changes = [];
|
|
258
303
|
exportsArray.forEach((node) => {
|
|
259
|
-
if (isOverride(node)) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
304
|
+
if (!isOverride(node)) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
let objectLiteralNode;
|
|
308
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
309
|
+
objectLiteralNode = node;
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// Handle compat.config(...).map(...) pattern
|
|
313
|
+
const arrowBody = node['expression'].arguments[0].body.expression;
|
|
314
|
+
if (ts.isObjectLiteralExpression(arrowBody)) {
|
|
315
|
+
objectLiteralNode = arrowBody;
|
|
266
316
|
}
|
|
267
317
|
else {
|
|
268
|
-
|
|
269
|
-
// strip any spread elements
|
|
270
|
-
objSource = fullNodeText.replace(SPREAD_ELEMENTS_REGEXP, '');
|
|
271
|
-
start =
|
|
272
|
-
node['expression'].arguments[0].body.expression.properties.pos +
|
|
273
|
-
(fullNodeText.length - objSource.length);
|
|
274
|
-
end = node['expression'].arguments[0].body.expression.properties.end;
|
|
318
|
+
return;
|
|
275
319
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
320
|
+
}
|
|
321
|
+
// Use AST-based extraction to handle variable references (e.g., plugins: { 'abc': abc })
|
|
322
|
+
const data = extractPropertiesFromObjectLiteral(objectLiteralNode);
|
|
323
|
+
if (lookup(data)) {
|
|
324
|
+
// Deep clone before update (update functions may mutate nested objects)
|
|
325
|
+
const originalData = structuredClone(data);
|
|
326
|
+
let updatedData = update?.(data);
|
|
327
|
+
if (updatedData) {
|
|
328
|
+
updatedData = mapFilePaths(updatedData);
|
|
329
|
+
const changedProps = findChangedProperties(originalData, updatedData);
|
|
330
|
+
for (const propName of changedProps) {
|
|
331
|
+
const originalNode = findPropertyNode(objectLiteralNode, propName);
|
|
332
|
+
const updatedValue = updatedData[propName];
|
|
333
|
+
if (originalNode && !(propName in updatedData)) {
|
|
334
|
+
// Delete property that was removed
|
|
335
|
+
changes.push({
|
|
336
|
+
type: devkit_1.ChangeType.Delete,
|
|
337
|
+
start: originalNode.pos,
|
|
338
|
+
length: originalNode.end - originalNode.pos,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
else if (originalNode) {
|
|
342
|
+
// Replace existing property value
|
|
343
|
+
const valueNode = originalNode.initializer;
|
|
344
|
+
changes.push({
|
|
345
|
+
type: devkit_1.ChangeType.Delete,
|
|
346
|
+
start: valueNode.pos,
|
|
347
|
+
length: valueNode.end - valueNode.pos,
|
|
348
|
+
});
|
|
349
|
+
changes.push({
|
|
350
|
+
type: devkit_1.ChangeType.Insert,
|
|
351
|
+
index: valueNode.pos,
|
|
352
|
+
text: ' ' + serializeValue(updatedValue, format),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
// Add new property at the end of the object
|
|
357
|
+
const lastProp = objectLiteralNode.properties[objectLiteralNode.properties.length - 1];
|
|
358
|
+
const insertPos = lastProp
|
|
359
|
+
? lastProp.end
|
|
360
|
+
: objectLiteralNode.pos + 1;
|
|
361
|
+
const needsComma = lastProp ? ',' : '';
|
|
362
|
+
changes.push({
|
|
363
|
+
type: devkit_1.ChangeType.Insert,
|
|
364
|
+
index: insertPos,
|
|
365
|
+
text: `${needsComma}\n "${propName}": ${serializeValue(updatedValue, format)}`,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
298
368
|
}
|
|
299
369
|
}
|
|
300
370
|
}
|