eslint-plugin-package-json 0.76.0 → 0.78.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/CHANGELOG.md CHANGED
@@ -1,11 +1,23 @@
1
1
  # Changelog
2
2
 
3
- # [0.76.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.75.0...v0.76.0) (2025-11-15)
3
+ # [0.78.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.77.0...v0.78.0) (2025-11-15)
4
+
5
+
6
+ ### Features
7
+
8
+ * **valid-repository:** add new rule for validating `repository` ([#1393](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1393)) ([2b38e88](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/2b38e881f60d357f9f73ad7a1aff159682542c42)), closes [#838](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/838)
4
9
 
10
+ # [0.77.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.76.0...v0.77.0) (2025-11-15)
11
+
12
+ ### Features
13
+
14
+ - **unique-dependencies:** report cross-group duplicates ([#1398](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1398)) ([94b690e](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/94b690e1996ec271ba743225ccecf66691f97e01)), closes [#1007](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1007)
15
+
16
+ # [0.76.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.75.0...v0.76.0) (2025-11-15)
5
17
 
6
18
  ### Features
7
19
 
8
- * **valid-engines:** add new rule for validating `engines` ([#1397](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1397)) ([ba834f0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/ba834f00651b64f2bc0cf58cf41d768bd6cee5eb)), closes [#826](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/826)
20
+ - **valid-engines:** add new rule for validating `engines` ([#1397](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1397)) ([ba834f0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/ba834f00651b64f2bc0cf58cf41d768bd6cee5eb)), closes [#826](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/826)
9
21
 
10
22
  # [0.75.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.73.0...v0.75.0) (2025-11-15)
11
23
 
package/README.md CHANGED
@@ -237,6 +237,7 @@ The default settings don't conflict, and Prettier plugins can quickly fix up ord
237
237
  | [valid-peerDependencies](docs/rules/valid-peerDependencies.md) | Enforce that the `peerDependencies` property is valid. | ✔️ ✅ | | | |
238
238
  | [valid-private](docs/rules/valid-private.md) | Enforce that the `private` property is valid. | ✔️ ✅ | | | |
239
239
  | [valid-publishConfig](docs/rules/valid-publishConfig.md) | Enforce that the `publishConfig` property is valid. | ✔️ ✅ | | | |
240
+ | [valid-repository](docs/rules/valid-repository.md) | Enforce that the `repository` property is valid. | ✔️ ✅ | | | |
240
241
  | [valid-repository-directory](docs/rules/valid-repository-directory.md) | Enforce that if repository directory is specified, it matches the path to the package.json file | ✔️ ✅ | | 💡 | |
241
242
  | [valid-scripts](docs/rules/valid-scripts.md) | Enforce that the `scripts` property is valid. | ✔️ ✅ | | | |
242
243
  | [valid-type](docs/rules/valid-type.md) | Enforce that the `type` property is valid. | ✔️ ✅ | | | |
@@ -14,6 +14,12 @@ const dependencyPropertyNames = new Set([
14
14
  ]);
15
15
  const rule = createRule({
16
16
  create(context) {
17
+ const dependenciesCache = {
18
+ dependencies: [],
19
+ devDependencies: [],
20
+ peerDependencies: []
21
+ };
22
+ const trackForCrossGroupUniqueness = Object.keys(dependenciesCache);
17
23
  function check(elements, getNodeToRemove) {
18
24
  const seen = /* @__PURE__ */ new Set();
19
25
  for (const element of elements.filter(isNotNullish).filter(isJSONStringLiteral).reverse()) if (seen.has(element.value)) report(element, elements);
@@ -30,17 +36,38 @@ const rule = createRule({
30
36
  });
31
37
  }
32
38
  }
33
- return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral]"(node) {
34
- if (!dependencyPropertyNames.has(node.key.value)) return;
35
- switch (node.value.type) {
36
- case "JSONArrayExpression":
37
- check(node.value.elements, (element) => element);
38
- break;
39
- case "JSONObjectExpression":
40
- check(node.value.properties.map((property) => property.key), (property) => property.parent);
41
- break;
39
+ return {
40
+ "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral]"(node) {
41
+ if (!dependencyPropertyNames.has(node.key.value)) return;
42
+ switch (node.value.type) {
43
+ case "JSONArrayExpression":
44
+ check(node.value.elements, (element) => element);
45
+ break;
46
+ case "JSONObjectExpression":
47
+ check(node.value.properties.map((property) => property.key), (property) => property.parent);
48
+ if (trackForCrossGroupUniqueness.includes(node.key.value)) dependenciesCache[node.key.value] = node.value.properties;
49
+ break;
50
+ }
51
+ },
52
+ "Program:exit"() {
53
+ const dependencyNames = new Set(dependenciesCache.dependencies.map((node) => node.key).filter(isJSONStringLiteral).map((dependencyNameNode) => dependencyNameNode.value));
54
+ if (!dependencyNames.size) return;
55
+ for (const dependencyType of ["devDependencies", "peerDependencies"]) {
56
+ const otherDependencies = dependenciesCache[dependencyType];
57
+ for (const otherDependencyNode of otherDependencies) {
58
+ const otherDependencyKey = otherDependencyNode.key;
59
+ if (isJSONStringLiteral(otherDependencyKey) && dependencyNames.has(otherDependencyKey.value)) context.report({
60
+ messageId: "crossGroupDuplicate",
61
+ node: otherDependencyNode,
62
+ suggest: [{
63
+ fix: fixRemoveObjectProperty(context, otherDependencyNode),
64
+ messageId: "remove"
65
+ }]
66
+ });
67
+ }
68
+ }
42
69
  }
43
- } };
70
+ };
44
71
  },
45
72
  meta: {
46
73
  docs: {
@@ -50,8 +77,9 @@ const rule = createRule({
50
77
  },
51
78
  hasSuggestions: true,
52
79
  messages: {
53
- overridden: "Package name is overridden by a duplicate listing later on.",
54
- remove: "Remove this redundant dependency listing."
80
+ crossGroupDuplicate: "Dependency is also declared in \"dependencies\" and is redundant",
81
+ overridden: "Dependency is overridden by a duplicate entry later on",
82
+ remove: "Remove this redundant dependency"
55
83
  },
56
84
  schema: [],
57
85
  type: "suggestion"
@@ -1,5 +1,5 @@
1
1
  import { createSimpleValidPropertyRule } from "../utils/createSimpleValidPropertyRule.mjs";
2
- import { validateAuthor, validateBin, validateBundleDependencies, validateConfig, validateContributors, validateCpu, validateDependencies, validateDescription, validateDirectories, validateEngines, validateExports, validateFiles, validateHomepage, validateKeywords, validateLicense, validateMain, validateMan, validateOs, validatePrivate, validatePublishConfig, validateScripts, validateType, validateWorkspaces } from "package-json-validator";
2
+ import { validateAuthor, validateBin, validateBundleDependencies, validateConfig, validateContributors, validateCpu, validateDependencies, validateDescription, validateDirectories, validateEngines, validateExports, validateFiles, validateHomepage, validateKeywords, validateLicense, validateMain, validateMan, validateOs, validatePrivate, validatePublishConfig, validateRepository, validateScripts, validateType, validateWorkspaces } from "package-json-validator";
3
3
 
4
4
  //#region src/rules/valid-properties.ts
5
5
  const properties = [
@@ -29,6 +29,7 @@ const properties = [
29
29
  ["peerDependencies", validateDependencies],
30
30
  ["private", validatePrivate],
31
31
  ["publishConfig", validatePublishConfig],
32
+ ["repository", validateRepository],
32
33
  ["scripts", validateScripts],
33
34
  ["type", validateType],
34
35
  ["workspaces", validateWorkspaces]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-package-json",
3
- "version": "0.76.0",
3
+ "version": "0.78.0",
4
4
  "description": "Rules for consistent, readable, and valid package.json files. 🗂️",
5
5
  "homepage": "https://github.com/JoshuaKGoldberg/eslint-plugin-package-json#readme",
6
6
  "bugs": {