@nx/eslint-plugin 23.2.0-beta.2 → 23.2.0-beta.3
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.
|
@@ -112,7 +112,6 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => `https://github.com/nrwl
|
|
|
112
112
|
const projPackageJsonDeps = (0, package_json_utils_1.getProductionDependencies)(packageJson);
|
|
113
113
|
const rootPackageJsonDeps = (0, package_json_utils_1.getAllDependencies)(rootPackageJson);
|
|
114
114
|
const catalogManager = (0, internal_1.getCatalogManager)(devkit_1.workspaceRoot);
|
|
115
|
-
const catalogDefs = catalogManager?.getCatalogDefinitions(devkit_1.workspaceRoot);
|
|
116
115
|
function catalogEntryMatchesInstalled(catalogVersionSpec, installedVersion) {
|
|
117
116
|
if (installedVersion === '*') {
|
|
118
117
|
return true;
|
|
@@ -126,29 +125,7 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => `https://github.com/nrwl
|
|
|
126
125
|
});
|
|
127
126
|
}
|
|
128
127
|
function getCatalogVersionForPackage(packageName) {
|
|
129
|
-
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
const matches = [];
|
|
133
|
-
// Check default catalog — `catalog` takes precedence over `catalogs.default`.
|
|
134
|
-
// Both existing simultaneously is a pnpm error caught by validateCatalogReference.
|
|
135
|
-
const defaultEntry = catalogDefs.catalog?.[packageName] ??
|
|
136
|
-
catalogDefs.catalogs?.default?.[packageName];
|
|
137
|
-
if (defaultEntry) {
|
|
138
|
-
matches.push({ catalogRef: 'catalog:', versionSpec: defaultEntry });
|
|
139
|
-
}
|
|
140
|
-
// Check named catalogs (skip "default" — handled above)
|
|
141
|
-
if (catalogDefs.catalogs) {
|
|
142
|
-
for (const [name, entries] of Object.entries(catalogDefs.catalogs)) {
|
|
143
|
-
if (name === 'default' || !entries?.[packageName]) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
matches.push({
|
|
147
|
-
catalogRef: `catalog:${name}`,
|
|
148
|
-
versionSpec: entries[packageName],
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
128
|
+
const matches = catalogManager?.getCatalogReferencesForPackage(devkit_1.workspaceRoot, packageName) ?? [];
|
|
152
129
|
if (!matches.length) {
|
|
153
130
|
return null;
|
|
154
131
|
}
|
|
@@ -11,7 +11,7 @@ export type Options = [
|
|
|
11
11
|
tsConfig?: string;
|
|
12
12
|
}
|
|
13
13
|
];
|
|
14
|
-
export type MessageIds = 'missingRequiredSchema' | 'invalidSchemaPath' | 'missingImplementation' | 'invalidImplementationPath' | 'invalidImplementationModule' | 'unableToReadImplementationExports' | 'invalidPromptPath' | 'invalidVersion' | 'missingVersion' | 'noGeneratorsOrSchematicsFound' | 'noExecutorsOrBuildersFound' | 'valueShouldBeObject';
|
|
14
|
+
export type MessageIds = 'missingRequiredSchema' | 'invalidSchemaPath' | 'missingImplementation' | 'invalidImplementationPath' | 'invalidImplementationModule' | 'unableToReadImplementationExports' | 'invalidPromptPath' | 'invalidVersion' | 'missingVersion' | 'noGeneratorsOrSchematicsFound' | 'noExecutorsOrBuildersFound' | 'valueShouldBeObject' | 'duplicateKey';
|
|
15
15
|
export declare const RULE_NAME = "nx-plugin-checks";
|
|
16
16
|
declare const _default: TSESLint.RuleModule<MessageIds, Options, unknown, TSESLint.RuleListener> & {
|
|
17
17
|
name: string;
|
|
@@ -23,5 +23,12 @@ export declare function validateEntry(baseNode: AST.JSONObjectExpression, key: s
|
|
|
23
23
|
export declare function validateImplementationNode(implementationNode: AST.JSONProperty, key: string, context: TSESLint.RuleContext<MessageIds, Options>, projects: Record<string, ProjectConfiguration>): void;
|
|
24
24
|
export declare function validatePromptNode(promptNode: AST.JSONProperty, key: string, context: TSESLint.RuleContext<MessageIds, Options>): void;
|
|
25
25
|
export declare function validatePackageGroup(baseNode: AST.JSONObjectExpression, context: TSESLint.RuleContext<MessageIds, Options>): void;
|
|
26
|
+
/**
|
|
27
|
+
* A duplicate key anywhere in these manifests silently drops data:
|
|
28
|
+
* JSON parsers keep only the last occurrence, so a duplicated generator,
|
|
29
|
+
* executor, or migration entry key discards the earlier definition with no
|
|
30
|
+
* error at runtime.
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateNoDuplicateKeys(node: AST.JSONObjectExpression | AST.JSONArrayExpression, context: TSESLint.RuleContext<MessageIds, Options>): void;
|
|
26
33
|
export declare function validateVersionJsonExpression(node: AST.JSONExpression, context: TSESLint.RuleContext<MessageIds, Options>): string | boolean;
|
|
27
34
|
export declare function checkIfIdentifierIsFunction(filePath: string, identifier: string): boolean;
|
|
@@ -7,6 +7,7 @@ exports.validateEntry = validateEntry;
|
|
|
7
7
|
exports.validateImplementationNode = validateImplementationNode;
|
|
8
8
|
exports.validatePromptNode = validatePromptNode;
|
|
9
9
|
exports.validatePackageGroup = validatePackageGroup;
|
|
10
|
+
exports.validateNoDuplicateKeys = validateNoDuplicateKeys;
|
|
10
11
|
exports.validateVersionJsonExpression = validateVersionJsonExpression;
|
|
11
12
|
exports.checkIfIdentifierIsFunction = checkIfIdentifierIsFunction;
|
|
12
13
|
const tslib_1 = require("tslib");
|
|
@@ -82,6 +83,7 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
82
83
|
missingImplementation: '{{ key }}: Missing required property - `implementation`',
|
|
83
84
|
invalidPromptPath: '{{ key }}: Prompt path should point to a valid file',
|
|
84
85
|
missingVersion: '{{ key }}: Missing required property - `version`',
|
|
86
|
+
duplicateKey: '{{ key }}: Duplicate key. JSON parsers keep only the last occurrence, silently dropping the earlier one',
|
|
85
87
|
},
|
|
86
88
|
},
|
|
87
89
|
defaultOptions: [DEFAULT_OPTIONS],
|
|
@@ -109,6 +111,7 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
109
111
|
}
|
|
110
112
|
return {
|
|
111
113
|
['JSONExpressionStatement > JSONObjectExpression'](node) {
|
|
114
|
+
validateNoDuplicateKeys(node, context);
|
|
112
115
|
if (sourceFilePath === generatorsJson) {
|
|
113
116
|
checkCollectionFileNode(node, 'generator', context, projects);
|
|
114
117
|
}
|
|
@@ -425,6 +428,43 @@ function validatePackageGroup(baseNode, context) {
|
|
|
425
428
|
}
|
|
426
429
|
}
|
|
427
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* A duplicate key anywhere in these manifests silently drops data:
|
|
433
|
+
* JSON parsers keep only the last occurrence, so a duplicated generator,
|
|
434
|
+
* executor, or migration entry key discards the earlier definition with no
|
|
435
|
+
* error at runtime.
|
|
436
|
+
*/
|
|
437
|
+
function validateNoDuplicateKeys(node, context) {
|
|
438
|
+
if (node.type === 'JSONObjectExpression') {
|
|
439
|
+
const seen = new Set();
|
|
440
|
+
for (const property of node.properties) {
|
|
441
|
+
const key = property.key.type === 'JSONLiteral'
|
|
442
|
+
? String(property.key.value)
|
|
443
|
+
: property.key.name;
|
|
444
|
+
if (seen.has(key)) {
|
|
445
|
+
context.report({
|
|
446
|
+
messageId: 'duplicateKey',
|
|
447
|
+
data: { key },
|
|
448
|
+
node: property.key,
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
seen.add(key);
|
|
452
|
+
if (property.value.type === 'JSONObjectExpression' ||
|
|
453
|
+
property.value.type === 'JSONArrayExpression') {
|
|
454
|
+
validateNoDuplicateKeys(property.value, context);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
for (const element of node.elements) {
|
|
460
|
+
if (element &&
|
|
461
|
+
(element.type === 'JSONObjectExpression' ||
|
|
462
|
+
element.type === 'JSONArrayExpression')) {
|
|
463
|
+
validateNoDuplicateKeys(element, context);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
428
468
|
function validateVersionJsonExpression(node, context) {
|
|
429
469
|
return (node &&
|
|
430
470
|
node.type === 'JSONLiteral' &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/eslint-plugin",
|
|
3
|
-
"version": "23.2.0-beta.
|
|
3
|
+
"version": "23.2.0-beta.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -101,11 +101,11 @@
|
|
|
101
101
|
"picocolors": "^1.1.0",
|
|
102
102
|
"semver": "^7.6.3",
|
|
103
103
|
"tslib": "^2.3.0",
|
|
104
|
-
"@nx/
|
|
105
|
-
"@nx/
|
|
104
|
+
"@nx/devkit": "23.2.0-beta.3",
|
|
105
|
+
"@nx/js": "23.2.0-beta.3"
|
|
106
106
|
},
|
|
107
107
|
"devDependencies": {
|
|
108
|
-
"nx": "23.2.0-beta.
|
|
108
|
+
"nx": "23.2.0-beta.3"
|
|
109
109
|
},
|
|
110
110
|
"publishConfig": {
|
|
111
111
|
"access": "public"
|