eslint-plugin-package-json 0.33.1 → 0.34.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.33.1](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.33.0...v0.33.1) (2025-06-01)
3
+ # [0.34.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.33.2...v0.34.0) (2025-06-10)
4
+
5
+
6
+ ### Features
7
+
8
+ * **valid-package-definition:** add ignoreProperties option ([#1077](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1077)) ([530e343](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/530e3430f87f21c9fadd4d511097d20e26f7190f)), closes [#1076](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1076)
4
9
 
10
+ ## [0.33.2](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.33.1...v0.33.2) (2025-06-01)
11
+
12
+ ### Bug Fixes
13
+
14
+ - prevent `no-redundant-files` crash with wildcard and `main` field ([#1078](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1078)) ([ad4f95f](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/ad4f95f382bce8d5d0ecc79e4242596dc3eec771)), closes [#1066](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1066)
15
+
16
+ ## [0.33.1](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.33.0...v0.33.1) (2025-06-01)
5
17
 
6
18
  ### Bug Fixes
7
19
 
8
- * add CHANGELOG to package ([#1075](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1075)) ([eb13030](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/eb130302b6dfcc456dfeaf49fdfd61bd4fa495d1)), closes [#1070](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1070)
20
+ - add CHANGELOG to package ([#1075](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1075)) ([eb13030](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/eb130302b6dfcc456dfeaf49fdfd61bd4fa495d1)), closes [#1070](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1070)
9
21
 
10
22
  # [0.33.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.32.0...v0.33.0) (2025-05-31)
11
23
 
package/lib/index.d.mts CHANGED
@@ -9,7 +9,9 @@ declare const configs: {
9
9
  "legacy-recommended": {
10
10
  plugins: string[];
11
11
  rules: {
12
- [k: string]: "error";
12
+ "package-json/valid-package-definition": ["error", {
13
+ ignoreProperties: string[];
14
+ }];
13
15
  };
14
16
  };
15
17
  recommended: {
@@ -29,7 +31,9 @@ declare const configs: {
29
31
  };
30
32
  };
31
33
  rules: {
32
- [k: string]: "error";
34
+ "package-json/valid-package-definition": ["error", {
35
+ ignoreProperties: string[];
36
+ }];
33
37
  };
34
38
  };
35
39
  };
package/lib/index.d.ts CHANGED
@@ -9,7 +9,9 @@ declare const configs: {
9
9
  "legacy-recommended": {
10
10
  plugins: string[];
11
11
  rules: {
12
- [k: string]: "error";
12
+ "package-json/valid-package-definition": ["error", {
13
+ ignoreProperties: string[];
14
+ }];
13
15
  };
14
16
  };
15
17
  recommended: {
@@ -29,7 +31,9 @@ declare const configs: {
29
31
  };
30
32
  };
31
33
  rules: {
32
- [k: string]: "error";
34
+ "package-json/valid-package-definition": ["error", {
35
+ ignoreProperties: string[];
36
+ }];
33
37
  };
34
38
  };
35
39
  };
package/lib/plugin.d.mts CHANGED
@@ -8,7 +8,9 @@ declare const plugin: {
8
8
  "legacy-recommended": {
9
9
  plugins: string[];
10
10
  rules: {
11
- [k: string]: "error";
11
+ "package-json/valid-package-definition": ["error", {
12
+ ignoreProperties: string[];
13
+ }];
12
14
  };
13
15
  };
14
16
  recommended: {
@@ -21,7 +23,9 @@ declare const plugin: {
21
23
  readonly "package-json": /*elided*/ any;
22
24
  };
23
25
  rules: {
24
- [k: string]: "error";
26
+ "package-json/valid-package-definition": ["error", {
27
+ ignoreProperties: string[];
28
+ }];
25
29
  };
26
30
  };
27
31
  };
package/lib/plugin.d.ts CHANGED
@@ -8,7 +8,9 @@ declare const plugin: {
8
8
  "legacy-recommended": {
9
9
  plugins: string[];
10
10
  rules: {
11
- [k: string]: "error";
11
+ "package-json/valid-package-definition": ["error", {
12
+ ignoreProperties: string[];
13
+ }];
12
14
  };
13
15
  };
14
16
  recommended: {
@@ -21,7 +23,9 @@ declare const plugin: {
21
23
  readonly "package-json": /*elided*/ any;
22
24
  };
23
25
  rules: {
24
- [k: string]: "error";
26
+ "package-json/valid-package-definition": ["error", {
27
+ ignoreProperties: string[];
28
+ }];
25
29
  };
26
30
  };
27
31
  };
package/lib/plugin.js CHANGED
@@ -77,9 +77,27 @@ const rules = {
77
77
  }
78
78
  }
79
79
  };
80
- const recommendedRules = Object.fromEntries(
81
- Object.entries(rules).filter(([, rule]) => rule.meta.docs?.recommended).map(([name2]) => ["package-json/" + name2, "error"])
82
- );
80
+ const baseRecommendedRules = {
81
+ ...Object.fromEntries(
82
+ Object.entries(rules).filter(([, rule]) => rule.meta.docs?.recommended).map(([name2]) => ["package-json/" + name2, "error"])
83
+ )
84
+ };
85
+ const recommendedRules = {
86
+ ...baseRecommendedRules,
87
+ // As we add more `valid-*` rules, we should prevent this legacy rule from
88
+ // also reporting the same errors.
89
+ "package-json/valid-package-definition": [
90
+ "error",
91
+ {
92
+ // Create a list of properties to ignore based on the valid-* rules
93
+ // we currently have. Once we've fully covered what `valid-package-definition`
94
+ // checks, we can remove it from the `recommended` config entirely.
95
+ ignoreProperties: Object.entries(baseRecommendedRules).filter(
96
+ ([name2]) => name2.startsWith("package-json/valid-") && name2 !== "package-json/valid-package-definition"
97
+ ).map(([name2]) => name2.replace("package-json/valid-", ""))
98
+ }
99
+ ]
100
+ };
83
101
  const plugin = {
84
102
  configs: {
85
103
  "legacy-recommended": {
package/lib/plugin.mjs CHANGED
@@ -43,9 +43,27 @@ const rules = {
43
43
  }
44
44
  }
45
45
  };
46
- const recommendedRules = Object.fromEntries(
47
- Object.entries(rules).filter(([, rule]) => rule.meta.docs?.recommended).map(([name2]) => ["package-json/" + name2, "error"])
48
- );
46
+ const baseRecommendedRules = {
47
+ ...Object.fromEntries(
48
+ Object.entries(rules).filter(([, rule]) => rule.meta.docs?.recommended).map(([name2]) => ["package-json/" + name2, "error"])
49
+ )
50
+ };
51
+ const recommendedRules = {
52
+ ...baseRecommendedRules,
53
+ // As we add more `valid-*` rules, we should prevent this legacy rule from
54
+ // also reporting the same errors.
55
+ "package-json/valid-package-definition": [
56
+ "error",
57
+ {
58
+ // Create a list of properties to ignore based on the valid-* rules
59
+ // we currently have. Once we've fully covered what `valid-package-definition`
60
+ // checks, we can remove it from the `recommended` config entirely.
61
+ ignoreProperties: Object.entries(baseRecommendedRules).filter(
62
+ ([name2]) => name2.startsWith("package-json/valid-") && name2 !== "package-json/valid-package-definition"
63
+ ).map(([name2]) => name2.replace("package-json/valid-", ""))
64
+ }
65
+ ]
66
+ };
49
67
  const plugin = {
50
68
  configs: {
51
69
  "legacy-recommended": {
@@ -30,8 +30,12 @@ const defaultFiles = [
30
30
  /^(\.\/)?README(\.|$)/i,
31
31
  /^(\.\/)?package\.json$/i
32
32
  ];
33
+ const wildcardsRegex = /[*?[\]{}]/;
33
34
  const cachedRegex = /* @__PURE__ */ new Map();
34
35
  const getCachedLocalFileRegex = (filename) => {
36
+ if (wildcardsRegex.test(filename)) {
37
+ return null;
38
+ }
35
39
  const baseFilename = filename.replace("./", "");
36
40
  let regex = cachedRegex.get(baseFilename);
37
41
  if (regex) {
@@ -132,7 +136,7 @@ const rule = (0, import_createRule.createRule)({
132
136
  const regex = getCachedLocalFileRegex(
133
137
  fileEntry.value
134
138
  );
135
- if (regex.test(fileToCheck)) {
139
+ if (regex?.test(fileToCheck)) {
136
140
  report(files, index, validation.messageId);
137
141
  }
138
142
  }
@@ -7,8 +7,12 @@ const defaultFiles = [
7
7
  /^(\.\/)?README(\.|$)/i,
8
8
  /^(\.\/)?package\.json$/i
9
9
  ];
10
+ const wildcardsRegex = /[*?[\]{}]/;
10
11
  const cachedRegex = /* @__PURE__ */ new Map();
11
12
  const getCachedLocalFileRegex = (filename) => {
13
+ if (wildcardsRegex.test(filename)) {
14
+ return null;
15
+ }
12
16
  const baseFilename = filename.replace("./", "");
13
17
  let regex = cachedRegex.get(baseFilename);
14
18
  if (regex) {
@@ -109,7 +113,7 @@ const rule = createRule({
109
113
  const regex = getCachedLocalFileRegex(
110
114
  fileEntry.value
111
115
  );
112
- if (regex.test(fileToCheck)) {
116
+ if (regex?.test(fileToCheck)) {
113
117
  report(files, index, validation.messageId);
114
118
  }
115
119
  }
@@ -3,8 +3,12 @@ import * as jsonc_eslint_parser from 'jsonc-eslint-parser';
3
3
  import { PackageJsonRuleContext } from '../createRule.mjs';
4
4
  import 'estree';
5
5
 
6
+ interface Option {
7
+ ignoreProperties?: string[];
8
+ }
9
+ type Options = [Option?];
6
10
  declare const rule: {
7
- create(context: PackageJsonRuleContext<unknown[]>): jsonc_eslint_parser.RuleListener;
11
+ create(context: PackageJsonRuleContext<Options>): jsonc_eslint_parser.RuleListener;
8
12
  meta: eslint.Rule.RuleMetaData;
9
13
  };
10
14
 
@@ -3,8 +3,12 @@ import * as jsonc_eslint_parser from 'jsonc-eslint-parser';
3
3
  import { PackageJsonRuleContext } from '../createRule.js';
4
4
  import 'estree';
5
5
 
6
+ interface Option {
7
+ ignoreProperties?: string[];
8
+ }
9
+ type Options = [Option?];
6
10
  declare const rule: {
7
- create(context: PackageJsonRuleContext<unknown[]>): jsonc_eslint_parser.RuleListener;
11
+ create(context: PackageJsonRuleContext<Options>): jsonc_eslint_parser.RuleListener;
8
12
  meta: eslint.Rule.RuleMetaData;
9
13
  };
10
14
 
@@ -31,18 +31,22 @@ const ignoredErrors = [
31
31
  const isUsableError = (errorText) => ignoredErrors.every((pattern) => !pattern.test(errorText));
32
32
  const rule = (0, import_createRule.createRule)({
33
33
  create(context) {
34
+ const ignoreProperties = context.options[0]?.ignoreProperties ?? [];
34
35
  return {
35
36
  "Program:exit"() {
36
37
  const validation = (0, import_package_json_validator.validate)(context.sourceCode.text);
37
- validation.errors?.filter(isUsableError).forEach((message) => {
38
- if (message) {
38
+ const usableErrors = validation.errors?.filter((error) => {
39
+ return isUsableError(error.message) && !ignoreProperties.includes(error.field);
40
+ }) ?? [];
41
+ for (const error of usableErrors) {
42
+ if (error.message) {
39
43
  context.report({
40
44
  // eslint-disable-next-line eslint-plugin/prefer-message-ids
41
- message,
45
+ message: error.message,
42
46
  node: context.sourceCode.ast
43
47
  });
44
48
  }
45
- });
49
+ }
46
50
  }
47
51
  };
48
52
  },
@@ -53,7 +57,20 @@ const rule = (0, import_createRule.createRule)({
53
57
  description: "Enforce that package.json has all properties required by the npm spec",
54
58
  recommended: true
55
59
  },
56
- schema: [],
60
+ schema: [
61
+ {
62
+ additionalProperties: false,
63
+ properties: {
64
+ ignoreProperties: {
65
+ items: {
66
+ type: "string"
67
+ },
68
+ type: "array"
69
+ }
70
+ },
71
+ type: "object"
72
+ }
73
+ ],
57
74
  type: "problem"
58
75
  }
59
76
  });
@@ -8,18 +8,22 @@ const ignoredErrors = [
8
8
  const isUsableError = (errorText) => ignoredErrors.every((pattern) => !pattern.test(errorText));
9
9
  const rule = createRule({
10
10
  create(context) {
11
+ const ignoreProperties = context.options[0]?.ignoreProperties ?? [];
11
12
  return {
12
13
  "Program:exit"() {
13
14
  const validation = validate(context.sourceCode.text);
14
- validation.errors?.filter(isUsableError).forEach((message) => {
15
- if (message) {
15
+ const usableErrors = validation.errors?.filter((error) => {
16
+ return isUsableError(error.message) && !ignoreProperties.includes(error.field);
17
+ }) ?? [];
18
+ for (const error of usableErrors) {
19
+ if (error.message) {
16
20
  context.report({
17
21
  // eslint-disable-next-line eslint-plugin/prefer-message-ids
18
- message,
22
+ message: error.message,
19
23
  node: context.sourceCode.ast
20
24
  });
21
25
  }
22
- });
26
+ }
23
27
  }
24
28
  };
25
29
  },
@@ -30,7 +34,20 @@ const rule = createRule({
30
34
  description: "Enforce that package.json has all properties required by the npm spec",
31
35
  recommended: true
32
36
  },
33
- schema: [],
37
+ schema: [
38
+ {
39
+ additionalProperties: false,
40
+ properties: {
41
+ ignoreProperties: {
42
+ items: {
43
+ type: "string"
44
+ },
45
+ type: "array"
46
+ }
47
+ },
48
+ type: "object"
49
+ }
50
+ ],
34
51
  type: "problem"
35
52
  }
36
53
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-package-json",
3
- "version": "0.33.1",
3
+ "version": "0.34.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": {
@@ -43,7 +43,7 @@
43
43
  "lint:spelling": "cspell \"**\" \".github/**/*\"",
44
44
  "prepare": "husky",
45
45
  "test": "vitest",
46
- "tsc": "tsc"
46
+ "typecheck": "tsc"
47
47
  },
48
48
  "lint-staged": {
49
49
  "*": "prettier --ignore-unknown --write"
@@ -53,7 +53,7 @@
53
53
  "detect-indent": "6.1.0",
54
54
  "detect-newline": "3.1.0",
55
55
  "eslint-fix-utils": "^0.2.0",
56
- "package-json-validator": "^0.10.0",
56
+ "package-json-validator": "~0.13.1",
57
57
  "semver": "^7.5.4",
58
58
  "sort-object-keys": "^1.1.3",
59
59
  "sort-package-json": "^3.0.0",
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
64
- "@eslint/js": "9.27.0",
64
+ "@eslint/js": "9.28.0",
65
65
  "@release-it/conventional-changelog": "10.0.0",
66
66
  "@types/eslint-plugin-markdown": "2.0.2",
67
67
  "@types/estree": "1.0.7",
@@ -69,25 +69,25 @@
69
69
  "@types/semver": "7.7.0",
70
70
  "@types/sort-object-keys": "1.1.3",
71
71
  "@types/validate-npm-package-name": "4.0.2",
72
- "@vitest/coverage-v8": "3.1.2",
72
+ "@vitest/coverage-v8": "3.2.0",
73
73
  "@vitest/eslint-plugin": "1.2.0",
74
74
  "console-fail-test": "0.5.0",
75
75
  "create-typescript-app": "2.42.0",
76
76
  "cspell": "8.19.0",
77
- "eslint": "9.27.0",
77
+ "eslint": "9.28.0",
78
78
  "eslint-doc-generator": "2.1.2",
79
79
  "eslint-plugin-eslint-plugin": "6.4.0",
80
- "eslint-plugin-jsdoc": "50.6.8",
80
+ "eslint-plugin-jsdoc": "50.7.0",
81
81
  "eslint-plugin-jsonc": "2.20.0",
82
82
  "eslint-plugin-markdown": "5.1.0",
83
- "eslint-plugin-n": "17.16.2",
83
+ "eslint-plugin-n": "17.19.0",
84
84
  "eslint-plugin-perfectionist": "4.13.0",
85
85
  "eslint-plugin-regexp": "2.7.0",
86
86
  "eslint-plugin-yml": "1.18.0",
87
87
  "husky": "9.1.7",
88
88
  "jsonc-eslint-parser": "2.4.0",
89
- "knip": "5.58.0",
90
- "lint-staged": "16.0.0",
89
+ "knip": "5.59.0",
90
+ "lint-staged": "16.1.0",
91
91
  "markdownlint": "0.38.0",
92
92
  "markdownlint-cli": "0.45.0",
93
93
  "prettier": "3.5.3",
@@ -98,8 +98,8 @@
98
98
  "sentences-per-line": "0.3.0",
99
99
  "tsup": "8.5.0",
100
100
  "typescript": "5.8.2",
101
- "typescript-eslint": "8.32.0",
102
- "vitest": "3.1.2"
101
+ "typescript-eslint": "8.33.0",
102
+ "vitest": "3.2.0"
103
103
  },
104
104
  "peerDependencies": {
105
105
  "eslint": ">=8.0.0",