@nx/eslint-plugin 16.5.0-beta.2 → 16.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/eslint-plugin",
3
- "version": "16.5.0-beta.2",
3
+ "version": "16.5.0",
4
4
  "private": false,
5
5
  "description": "The eslint-plugin package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called enforce-module-boundaries.",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "homepage": "https://nx.dev",
26
26
  "peerDependencies": {
27
- "@typescript-eslint/parser": "^5.58.0",
27
+ "@typescript-eslint/parser": "^5.60.1",
28
28
  "eslint-config-prettier": "^8.1.0"
29
29
  },
30
30
  "peerDependenciesMeta": {
@@ -33,11 +33,11 @@
33
33
  }
34
34
  },
35
35
  "dependencies": {
36
- "@nrwl/eslint-plugin-nx": "16.5.0-beta.2",
37
- "@nx/devkit": "16.5.0-beta.2",
38
- "@nx/js": "16.5.0-beta.2",
39
- "@typescript-eslint/type-utils": "^5.58.0",
40
- "@typescript-eslint/utils": "^5.58.0",
36
+ "@nrwl/eslint-plugin-nx": "16.5.0",
37
+ "@nx/devkit": "16.5.0",
38
+ "@nx/js": "16.5.0",
39
+ "@typescript-eslint/type-utils": "^5.60.1",
40
+ "@typescript-eslint/utils": "^5.60.1",
41
41
  "chalk": "^4.1.0",
42
42
  "confusing-browser-globals": "^1.0.9",
43
43
  "jsonc-eslint-parser": "^2.1.0",
@@ -50,5 +50,5 @@
50
50
  "migrations": "./migrations.json"
51
51
  },
52
52
  "types": "./src/index.d.ts",
53
- "gitHead": "efdf140459e453c50f06cf287906c4bb3ac49d3d"
53
+ "gitHead": "eaebcc34f92db2200dab0bde2e2e1dde107a47bf"
54
54
  }
@@ -34,7 +34,7 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
34
34
  },
35
35
  ],
36
36
  messages: {
37
- missingDependency: `The "{{projectName}}" uses the package "{{packageName}}", but it is missing from the project's "package.json".`,
37
+ missingDependency: `The "{{projectName}}" uses the following packages, but they are missing from the "{{section}}":{{packageNames}}`,
38
38
  obsoleteDependency: `The "{{packageName}}" package is not used by "{{projectName}}".`,
39
39
  versionMismatch: `The version specifier does not contain the installed version of "{{packageName}}" package: {{version}}.`,
40
40
  missingDependencySection: `Dependency sections are missing from the "package.json" but following dependencies were detected:{{dependencies}}`,
@@ -91,27 +91,34 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
91
91
  if (!checkMissingDependencies) {
92
92
  return;
93
93
  }
94
- const missingDeps = expectedDependencyNames.filter((d) => !projPackageJsonDeps[d]);
95
- missingDeps.forEach((d) => {
96
- if (!ignoredDependencies.includes(d)) {
97
- context.report({
98
- node: node,
99
- messageId: 'missingDependency',
100
- data: { packageName: d, projectName: sourceProject.name },
101
- fix(fixer) {
94
+ const missingDeps = expectedDependencyNames.filter((d) => !projPackageJsonDeps[d] && !ignoredDependencies.includes(d));
95
+ if (missingDeps.length) {
96
+ context.report({
97
+ node: node,
98
+ messageId: 'missingDependency',
99
+ data: {
100
+ packageNames: missingDeps.map((d) => `\n - ${d}`).join(''),
101
+ section: node.key.value,
102
+ projectName: sourceProject.name,
103
+ },
104
+ fix(fixer) {
105
+ missingDeps.forEach((d) => {
102
106
  projPackageJsonDeps[d] =
103
107
  rootPackageJsonDeps[d] || projDependencies[d];
104
- const deps = node.value.properties;
105
- if (deps.length) {
106
- return fixer.insertTextAfter(deps[deps.length - 1], `,\n "${d}": "${projPackageJsonDeps[d]}"`);
107
- }
108
- else {
109
- return fixer.replaceTextRange([node.value.range[0] + 1, node.value.range[1] - 1], `\n "${d}": "${projPackageJsonDeps[d]}"\n `);
110
- }
111
- },
112
- });
113
- }
114
- });
108
+ });
109
+ const deps = node.value.properties;
110
+ const mappedDeps = missingDeps
111
+ .map((d) => `\n "${d}": "${projPackageJsonDeps[d]}"`)
112
+ .join(',');
113
+ if (deps.length) {
114
+ return fixer.insertTextAfter(deps[deps.length - 1], `,${mappedDeps}`);
115
+ }
116
+ else {
117
+ return fixer.insertTextAfterRange([node.value.range[0] + 1, node.value.range[1] - 1], `${mappedDeps}\n `);
118
+ }
119
+ },
120
+ });
121
+ }
115
122
  }
116
123
  function validateVersionMatchesInstalled(node, packageName, packageRange) {
117
124
  if (!checkVersionMismatches) {
@@ -145,7 +152,7 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
145
152
  if (index > 0) {
146
153
  const previousNode = node.parent.properties[index - 1];
147
154
  return fixer.removeRange([
148
- previousNode.range[1] + 1,
155
+ previousNode.range[1] + (isLastProperty ? 0 : 1),
149
156
  node.range[1] + (isLastProperty ? 0 : 1),
150
157
  ]);
151
158
  }
@@ -165,13 +172,6 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
165
172
  ]);
166
173
  }
167
174
  }
168
- // remove 4 spaces, new line and potential comma from previous line
169
- const shouldRemoveSiblingComma = isLastProperty && node.parent.properties.length > 1;
170
- const leadingChars = 5 + (shouldRemoveSiblingComma ? 1 : 0);
171
- return fixer.removeRange([
172
- node.range[0] - leadingChars,
173
- node.range[1] + (isLastProperty ? 0 : 1),
174
- ]);
175
175
  },
176
176
  });
177
177
  }
@@ -66,8 +66,8 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
66
66
  noImportOfNonBuildableLibraries: 'Buildable libraries cannot import or export from non-buildable libraries',
67
67
  noImportsOfLazyLoadedLibraries: `Static imports of lazy-loaded libraries are forbidden.\n\nLibrary "{{targetProjectName}}" is lazy-loaded in these files:\n{{filePaths}}`,
68
68
  projectWithoutTagsCannotHaveDependencies: `A project without tags matching at least one constraint cannot depend on any libraries`,
69
- bannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import the "{{package}}" package`,
70
- nestedBannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import the "{{package}}" package. Nested import found at {{childProjectName}}`,
69
+ bannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import "{{imp}}"`,
70
+ nestedBannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import "{{imp}}". Nested import found at {{childProjectName}}`,
71
71
  noTransitiveDependencies: `Transitive dependencies are not allowed. Only packages defined in the "package.json" can be imported`,
72
72
  onlyTagsConstraintViolation: `A project tagged with "{{sourceTag}}" can only depend on libs tagged with {{tags}}`,
73
73
  emptyOnlyTagsConstraintViolation: 'A project tagged with "{{sourceTag}}" cannot depend on any libs with tags',
@@ -237,7 +237,7 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
237
237
  messageId: 'noTransitiveDependencies',
238
238
  });
239
239
  }
240
- const constraint = (0, runtime_lint_utils_1.hasBannedImport)(sourceProject, targetProject, depConstraints);
240
+ const constraint = (0, runtime_lint_utils_1.hasBannedImport)(sourceProject, targetProject, depConstraints, imp);
241
241
  if (constraint) {
242
242
  context.report({
243
243
  node,
@@ -246,7 +246,7 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
246
246
  sourceTag: (0, runtime_lint_utils_1.isComboDepConstraint)(constraint)
247
247
  ? constraint.allSourceTags.join('" and "')
248
248
  : constraint.sourceTag,
249
- package: targetProject.data.packageName,
249
+ imp,
250
250
  },
251
251
  });
252
252
  }
@@ -392,18 +392,18 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
392
392
  if (checkNestedExternalImports &&
393
393
  constraint.bannedExternalImports &&
394
394
  constraint.bannedExternalImports.length) {
395
- const matches = (0, runtime_lint_utils_1.hasBannedDependencies)(transitiveExternalDeps, projectGraph, constraint);
395
+ const matches = (0, runtime_lint_utils_1.hasBannedDependencies)(transitiveExternalDeps, projectGraph, constraint, imp);
396
396
  if (matches.length > 0) {
397
397
  matches.forEach(([target, violatingSource, constraint]) => {
398
398
  context.report({
399
399
  node,
400
- messageId: 'bannedExternalImportsViolation',
400
+ messageId: 'nestedBannedExternalImportsViolation',
401
401
  data: {
402
402
  sourceTag: (0, runtime_lint_utils_1.isComboDepConstraint)(constraint)
403
403
  ? constraint.allSourceTags.join('" and "')
404
404
  : constraint.sourceTag,
405
405
  childProjectName: violatingSource.name,
406
- package: target.data.packageName,
406
+ imp,
407
407
  },
408
408
  });
409
409
  });
@@ -41,7 +41,7 @@ export declare function findProjectUsingImport(projectGraph: ProjectGraph, targe
41
41
  export declare function findConstraintsFor(depConstraints: DepConstraint[], sourceProject: ProjectGraphProjectNode): DepConstraint[];
42
42
  export declare function onlyLoadChildren(graph: ProjectGraph, sourceProjectName: string, targetProjectName: string, visited: string[]): any;
43
43
  export declare function getSourceFilePath(sourceFileName: string, projectPath: string): string;
44
- export declare function hasBannedImport(source: ProjectGraphProjectNode, target: ProjectGraphExternalNode, depConstraints: DepConstraint[]): DepConstraint | undefined;
44
+ export declare function hasBannedImport(source: ProjectGraphProjectNode, target: ProjectGraphExternalNode, depConstraints: DepConstraint[], imp: string): DepConstraint | undefined;
45
45
  /**
46
46
  * Find all unique (transitive) external dependencies of given project
47
47
  * @param graph
@@ -56,7 +56,7 @@ export declare function findTransitiveExternalDependencies(graph: ProjectGraph,
56
56
  * @param depConstraint
57
57
  * @returns
58
58
  */
59
- export declare function hasBannedDependencies(externalDependencies: ProjectGraphDependency[], graph: ProjectGraph, depConstraint: DepConstraint): Array<[ProjectGraphExternalNode, ProjectGraphProjectNode, DepConstraint]> | undefined;
59
+ export declare function hasBannedDependencies(externalDependencies: ProjectGraphDependency[], graph: ProjectGraph, depConstraint: DepConstraint, imp: string): Array<[ProjectGraphExternalNode, ProjectGraphProjectNode, DepConstraint]> | undefined;
60
60
  export declare function isDirectDependency(source: ProjectGraphProjectNode, target: ProjectGraphExternalNode): boolean;
61
61
  /**
62
62
  * Verifies whether the given node has a builder target
@@ -150,17 +150,21 @@ exports.getSourceFilePath = getSourceFilePath;
150
150
  * @param depConstraints
151
151
  * @returns
152
152
  */
153
- function isConstraintBanningProject(externalProject, constraint) {
153
+ function isConstraintBanningProject(externalProject, constraint, imp) {
154
154
  const { allowedExternalImports, bannedExternalImports } = constraint;
155
155
  const { packageName } = externalProject.data;
156
+ if (imp !== packageName && !imp.startsWith(`${packageName}/`)) {
157
+ return false;
158
+ }
156
159
  /* Check if import is banned... */
157
- if (bannedExternalImports === null || bannedExternalImports === void 0 ? void 0 : bannedExternalImports.some((importDefinition) => mapGlobToRegExp(importDefinition).test(packageName))) {
160
+ if (bannedExternalImports === null || bannedExternalImports === void 0 ? void 0 : bannedExternalImports.some((importDefinition) => mapGlobToRegExp(importDefinition).test(imp))) {
158
161
  return true;
159
162
  }
160
163
  /* ... then check if there is a whitelist and if there is a match in the whitelist. */
161
- return allowedExternalImports === null || allowedExternalImports === void 0 ? void 0 : allowedExternalImports.every((importDefinition) => !mapGlobToRegExp(importDefinition).test(packageName));
164
+ return allowedExternalImports === null || allowedExternalImports === void 0 ? void 0 : allowedExternalImports.every((importDefinition) => !imp.startsWith(packageName) ||
165
+ !mapGlobToRegExp(importDefinition).test(imp));
162
166
  }
163
- function hasBannedImport(source, target, depConstraints) {
167
+ function hasBannedImport(source, target, depConstraints, imp) {
164
168
  // return those constraints that match source project
165
169
  depConstraints = depConstraints.filter((c) => {
166
170
  let tags = [];
@@ -172,7 +176,7 @@ function hasBannedImport(source, target, depConstraints) {
172
176
  }
173
177
  return tags.every((t) => hasTag(source, t));
174
178
  });
175
- return depConstraints.find((constraint) => isConstraintBanningProject(target, constraint));
179
+ return depConstraints.find((constraint) => isConstraintBanningProject(target, constraint, imp));
176
180
  }
177
181
  exports.hasBannedImport = hasBannedImport;
178
182
  /**
@@ -214,9 +218,9 @@ exports.findTransitiveExternalDependencies = findTransitiveExternalDependencies;
214
218
  * @param depConstraint
215
219
  * @returns
216
220
  */
217
- function hasBannedDependencies(externalDependencies, graph, depConstraint) {
221
+ function hasBannedDependencies(externalDependencies, graph, depConstraint, imp) {
218
222
  return externalDependencies
219
- .filter((dependency) => isConstraintBanningProject(graph.externalNodes[dependency.target], depConstraint))
223
+ .filter((dependency) => isConstraintBanningProject(graph.externalNodes[dependency.target], depConstraint, imp))
220
224
  .map((dep) => [
221
225
  graph.externalNodes[dep.target],
222
226
  graph.nodes[dep.source],