eslint-plugin-package-json 0.52.0 → 0.53.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/lib/createRule.d.ts +28 -28
  3. package/lib/createRule.js +18 -12
  4. package/lib/index.d.ts +33 -35
  5. package/lib/index.js +6 -6
  6. package/lib/plugin.d.ts +33 -34
  7. package/lib/plugin.js +62 -80
  8. package/lib/rules/no-empty-fields.d.ts +6 -11
  9. package/lib/rules/no-empty-fields.js +80 -112
  10. package/lib/rules/no-redundant-files.d.ts +5 -10
  11. package/lib/rules/no-redundant-files.js +93 -136
  12. package/lib/rules/order-properties.d.ts +6 -11
  13. package/lib/rules/order-properties.js +92 -116
  14. package/lib/rules/repository-shorthand.d.ts +6 -11
  15. package/lib/rules/repository-shorthand.js +79 -112
  16. package/lib/rules/require-properties.d.ts +7 -12
  17. package/lib/rules/require-properties.js +31 -27
  18. package/lib/rules/restrict-dependency-ranges.d.ts +9 -14
  19. package/lib/rules/restrict-dependency-ranges.js +137 -189
  20. package/lib/rules/sort-collections.d.ts +5 -10
  21. package/lib/rules/sort-collections.js +71 -124
  22. package/lib/rules/unique-dependencies.d.ts +5 -10
  23. package/lib/rules/unique-dependencies.js +58 -82
  24. package/lib/rules/valid-bin.d.ts +6 -11
  25. package/lib/rules/valid-bin.js +59 -78
  26. package/lib/rules/valid-local-dependency.d.ts +5 -10
  27. package/lib/rules/valid-local-dependency.js +49 -57
  28. package/lib/rules/valid-name.d.ts +5 -10
  29. package/lib/rules/valid-name.js +41 -48
  30. package/lib/rules/valid-package-definition.d.ts +6 -11
  31. package/lib/rules/valid-package-definition.js +41 -50
  32. package/lib/rules/valid-properties.d.ts +7 -7
  33. package/lib/rules/valid-properties.js +33 -55
  34. package/lib/rules/valid-repository-directory.d.ts +5 -10
  35. package/lib/rules/valid-repository-directory.js +65 -80
  36. package/lib/rules/valid-version.d.ts +5 -10
  37. package/lib/rules/valid-version.js +35 -36
  38. package/lib/types/estree.d.ts +8 -0
  39. package/lib/utils/createSimpleRequirePropertyRule.d.ts +19 -18
  40. package/lib/utils/createSimpleRequirePropertyRule.js +48 -53
  41. package/lib/utils/createSimpleValidPropertyRule.d.ts +6 -8
  42. package/lib/utils/createSimpleValidPropertyRule.js +45 -39
  43. package/lib/utils/findPropertyWithKeyValue.d.ts +6 -5
  44. package/lib/utils/findPropertyWithKeyValue.js +5 -6
  45. package/lib/utils/formatErrors.d.ts +3 -2
  46. package/lib/utils/formatErrors.js +11 -7
  47. package/lib/utils/isPackageJson.d.ts +3 -2
  48. package/lib/utils/isPackageJson.js +4 -3
  49. package/lib/utils/predicates.d.ts +4 -3
  50. package/lib/utils/predicates.js +6 -6
  51. package/package.json +8 -8
  52. package/lib/tests/rules/ruleTester.d.ts +0 -15
  53. package/lib/tests/rules/ruleTester.js +0 -25
  54. package/lib/types/estree.d.d.ts +0 -7
  55. package/lib/types/estree.d.js +0 -0
@@ -1,124 +1,100 @@
1
+ import { createRule } from "../createRule.js";
1
2
  import detectIndent from "detect-indent";
2
3
  import { detectNewlineGraceful } from "detect-newline";
3
4
  import sortObjectKeys from "sort-object-keys";
4
5
  import { sortOrder } from "sort-package-json";
5
- import { createRule } from "../createRule.js";
6
+
7
+ //#region src/rules/order-properties.ts
6
8
  const standardOrderLegacy = [
7
- "name",
8
- "version",
9
- "private",
10
- "publishConfig",
11
- "description",
12
- "main",
13
- "exports",
14
- "browser",
15
- "files",
16
- "bin",
17
- "directories",
18
- "man",
19
- "scripts",
20
- "repository",
21
- "keywords",
22
- "author",
23
- "license",
24
- "bugs",
25
- "homepage",
26
- "config",
27
- "dependencies",
28
- "devDependencies",
29
- "peerDependencies",
30
- "optionalDependencies",
31
- "bundledDependencies",
32
- "engines",
33
- "os",
34
- "cpu"
9
+ "name",
10
+ "version",
11
+ "private",
12
+ "publishConfig",
13
+ "description",
14
+ "main",
15
+ "exports",
16
+ "browser",
17
+ "files",
18
+ "bin",
19
+ "directories",
20
+ "man",
21
+ "scripts",
22
+ "repository",
23
+ "keywords",
24
+ "author",
25
+ "license",
26
+ "bugs",
27
+ "homepage",
28
+ "config",
29
+ "dependencies",
30
+ "devDependencies",
31
+ "peerDependencies",
32
+ "optionalDependencies",
33
+ "bundledDependencies",
34
+ "engines",
35
+ "os",
36
+ "cpu"
35
37
  ];
36
38
  const rule = createRule({
37
- create(context) {
38
- return {
39
- "Program:exit"() {
40
- const { ast, text } = context.sourceCode;
41
- const options = {
42
- order: "sort-package-json",
43
- ...context.options[0]
44
- };
45
- const requiredOrder = options.order === "legacy" ? standardOrderLegacy : options.order === "sort-package-json" ? sortOrder : options.order;
46
- const json = JSON.parse(text);
47
- const orderedSource = sortObjectKeys(json, [
48
- ...requiredOrder,
49
- ...Object.keys(json)
50
- ]);
51
- const orderedKeys = Object.keys(orderedSource);
52
- const { properties } = ast.body[0].expression;
53
- for (let i = 0; i < properties.length; i += 1) {
54
- const property = properties[i].key;
55
- const { value } = property;
56
- if (value === orderedKeys[i]) {
57
- continue;
58
- }
59
- context.report({
60
- data: {
61
- property: value
62
- },
63
- fix(fixer) {
64
- const { indent, type } = detectIndent(text);
65
- const endCharacters = text.endsWith("\n") ? "\n" : "";
66
- const newline = detectNewlineGraceful(text);
67
- let result = JSON.stringify(
68
- orderedSource,
69
- null,
70
- type === "tab" ? " " : indent
71
- ) + endCharacters;
72
- if (newline === "\r\n") {
73
- result = result.replace(/\n/g, newline);
74
- }
75
- return fixer.replaceText(
76
- context.sourceCode.ast,
77
- result
78
- );
79
- },
80
- loc: properties[i].loc,
81
- messageId: "incorrectOrder"
82
- });
83
- }
84
- }
85
- };
86
- },
87
- meta: {
88
- docs: {
89
- category: "Best Practices",
90
- description: "Package properties must be declared in standard order",
91
- recommended: true
92
- },
93
- fixable: "code",
94
- messages: {
95
- incorrectOrder: 'Package top-level property "{{property}}" is not ordered in the npm standard way. Run the ESLint auto-fixer to correct.'
96
- },
97
- schema: [
98
- {
99
- additionalProperties: false,
100
- properties: {
101
- order: {
102
- anyOf: [
103
- {
104
- enum: ["legacy", "sort-package-json"],
105
- type: ["string"]
106
- },
107
- {
108
- items: {
109
- type: ["string"]
110
- },
111
- type: ["array"]
112
- }
113
- ]
114
- }
115
- },
116
- type: "object"
117
- }
118
- ],
119
- type: "layout"
120
- }
39
+ create(context) {
40
+ return { "Program:exit"() {
41
+ const { ast, text } = context.sourceCode;
42
+ const options = {
43
+ order: "sort-package-json",
44
+ ...context.options[0]
45
+ };
46
+ const requiredOrder = options.order === "legacy" ? standardOrderLegacy : options.order === "sort-package-json" ? sortOrder : options.order;
47
+ const json = JSON.parse(text);
48
+ const orderedSource = sortObjectKeys(json, [...requiredOrder, ...Object.keys(json)]);
49
+ const orderedKeys = Object.keys(orderedSource);
50
+ const { properties } = ast.body[0].expression;
51
+ for (let i = 0; i < properties.length; i += 1) {
52
+ const property = properties[i].key;
53
+ const { value } = property;
54
+ if (value === orderedKeys[i]) continue;
55
+ context.report({
56
+ data: { property: value },
57
+ fix(fixer) {
58
+ const { indent, type } = detectIndent(text);
59
+ const endCharacters = text.endsWith("\n") ? "\n" : "";
60
+ const newline = detectNewlineGraceful(text);
61
+ let result = JSON.stringify(orderedSource, null, type === "tab" ? " " : indent) + endCharacters;
62
+ if (newline === "\r\n") result = result.replace(/\n/g, newline);
63
+ return fixer.replaceText(context.sourceCode.ast, result);
64
+ },
65
+ loc: properties[i].loc,
66
+ messageId: "incorrectOrder"
67
+ });
68
+ }
69
+ } };
70
+ },
71
+ meta: {
72
+ defaultOptions: [{ order: "sort-package-json" }],
73
+ docs: {
74
+ category: "Best Practices",
75
+ description: "Package properties must be declared in standard order",
76
+ recommended: true
77
+ },
78
+ fixable: "code",
79
+ messages: { incorrectOrder: "Package top-level property \"{{property}}\" is not ordered in the npm standard way. Run the ESLint auto-fixer to correct." },
80
+ schema: [{
81
+ additionalProperties: false,
82
+ properties: { order: {
83
+ anyOf: [{
84
+ enum: ["legacy", "sort-package-json"],
85
+ type: ["string"]
86
+ }, {
87
+ items: { type: ["string"] },
88
+ type: ["array"]
89
+ }],
90
+ description: "Specifies the sorting order of top-level properties."
91
+ } },
92
+ type: "object"
93
+ }],
94
+ type: "layout"
95
+ },
96
+ name: "order-properties"
121
97
  });
122
- export {
123
- rule
124
- };
98
+
99
+ //#endregion
100
+ export { rule };
@@ -1,15 +1,10 @@
1
- import * as eslint from 'eslint';
2
- import * as jsonc_eslint_parser from 'jsonc-eslint-parser';
3
- import { PackageJsonRuleContext } from '../createRule.js';
4
- import 'estree';
1
+ import { PackageJsonRuleModule } from "../createRule.js";
5
2
 
3
+ //#region src/rules/repository-shorthand.d.ts
6
4
  type Form = "object" | "shorthand";
7
5
  type Options = [{
8
- form: Form;
6
+ form: Form;
9
7
  }?];
10
- declare const rule: {
11
- create(context: PackageJsonRuleContext<Options>): jsonc_eslint_parser.RuleListener;
12
- meta: eslint.Rule.RuleMetaData;
13
- };
14
-
15
- export { rule };
8
+ declare const rule: PackageJsonRuleModule<Options>;
9
+ //#endregion
10
+ export { rule };
@@ -1,119 +1,86 @@
1
1
  import { createRule } from "../createRule.js";
2
- import { findPropertyWithKeyValue } from "../utils/findPropertyWithKeyValue.js";
3
2
  import { isJSONStringLiteral } from "../utils/predicates.js";
3
+ import { findPropertyWithKeyValue } from "../utils/findPropertyWithKeyValue.js";
4
+
5
+ //#region src/rules/repository-shorthand.ts
4
6
  const githubUrlRegex = /^(?:git\+)?(?:ssh:\/\/git@|http?s:\/\/)?(?:www\.)?github\.com\//;
5
7
  const isGitHubUrl = (url) => githubUrlRegex.test(url);
6
8
  const cleanGitHubUrl = (url) => url.replace(githubUrlRegex, "").replace(/\.git$/, "");
7
9
  const rule = createRule({
8
- create(context) {
9
- const [{ form = "object" } = {}] = context.options;
10
- function validateRepositoryForObject(node) {
11
- if (isJSONStringLiteral(node.value)) {
12
- context.report({
13
- fix(fixer) {
14
- if (!isJSONStringLiteral(node.value) || node.value.value.split("/").filter(Boolean).length !== 2) {
15
- return null;
16
- }
17
- return fixer.replaceText(
18
- node.value,
19
- JSON.stringify(
20
- {
21
- type: "git",
22
- url: `https://github.com/${node.value.value}`
23
- },
24
- null,
25
- 2
26
- )
27
- );
28
- },
29
- messageId: "preferObject",
30
- node: node.value
31
- });
32
- }
33
- }
34
- function validateRepositoryForShorthand(node) {
35
- if (isJSONStringLiteral(node.value)) {
36
- const { value } = node.value;
37
- if (typeof value === "string" && isGitHubUrl(value)) {
38
- context.report({
39
- fix(fixer) {
40
- return fixer.replaceText(
41
- node.value,
42
- JSON.stringify(cleanGitHubUrl(value))
43
- );
44
- },
45
- messageId: "preferShorthand",
46
- node: node.value
47
- });
48
- }
49
- return;
50
- }
51
- if (node.value.type !== "JSONObjectExpression") {
52
- return;
53
- }
54
- const { properties } = node.value;
55
- if (findPropertyWithKeyValue(properties, "directory")) {
56
- return;
57
- }
58
- const typeProperty = findPropertyWithKeyValue(properties, "type");
59
- if (typeProperty?.value.type !== "JSONLiteral" || typeProperty.value.value !== "git") {
60
- return;
61
- }
62
- const urlProperty = findPropertyWithKeyValue(properties, "url");
63
- if (urlProperty?.value.type !== "JSONLiteral" || typeof urlProperty.value.value !== "string" || !isGitHubUrl(urlProperty.value.value)) {
64
- return;
65
- }
66
- const url = urlProperty.value.value;
67
- context.report({
68
- fix(fixer) {
69
- return fixer.replaceText(
70
- node.value,
71
- JSON.stringify(cleanGitHubUrl(url))
72
- );
73
- },
74
- messageId: "preferShorthand",
75
- node: node.value
76
- });
77
- }
78
- return {
79
- JSONProperty(node) {
80
- if (node.key.type !== "JSONLiteral" || node.key.value !== "repository" || node.parent.parent.parent.type !== "Program") {
81
- return;
82
- }
83
- if (form === "shorthand") {
84
- validateRepositoryForShorthand(node);
85
- } else {
86
- validateRepositoryForObject(node);
87
- }
88
- }
89
- };
90
- },
91
- meta: {
92
- docs: {
93
- category: "Best Practices",
94
- description: "Enforce either object or shorthand declaration for repository.",
95
- recommended: true
96
- },
97
- fixable: "code",
98
- messages: {
99
- preferObject: "Prefer an object locator for a repository.",
100
- preferShorthand: "Prefer a shorthand locator for a GitHub repository."
101
- },
102
- schema: [
103
- {
104
- additionalProperties: false,
105
- properties: {
106
- form: {
107
- enum: ["object", "shorthand"],
108
- type: ["string"]
109
- }
110
- },
111
- type: "object"
112
- }
113
- ],
114
- type: "suggestion"
115
- }
10
+ create(context) {
11
+ const [{ form = "object" } = {}] = context.options;
12
+ function validateRepositoryForObject(node) {
13
+ if (isJSONStringLiteral(node.value)) context.report({
14
+ fix(fixer) {
15
+ if (!isJSONStringLiteral(node.value) || node.value.value.split("/").filter(Boolean).length !== 2) return null;
16
+ return fixer.replaceText(node.value, JSON.stringify({
17
+ type: "git",
18
+ url: `https://github.com/${node.value.value}`
19
+ }, null, 2));
20
+ },
21
+ messageId: "preferObject",
22
+ node: node.value
23
+ });
24
+ }
25
+ function validateRepositoryForShorthand(node) {
26
+ if (isJSONStringLiteral(node.value)) {
27
+ const { value } = node.value;
28
+ if (typeof value === "string" && isGitHubUrl(value)) context.report({
29
+ fix(fixer) {
30
+ return fixer.replaceText(node.value, JSON.stringify(cleanGitHubUrl(value)));
31
+ },
32
+ messageId: "preferShorthand",
33
+ node: node.value
34
+ });
35
+ return;
36
+ }
37
+ if (node.value.type !== "JSONObjectExpression") return;
38
+ const { properties } = node.value;
39
+ if (findPropertyWithKeyValue(properties, "directory")) return;
40
+ const typeProperty = findPropertyWithKeyValue(properties, "type");
41
+ if (typeProperty?.value.type !== "JSONLiteral" || typeProperty.value.value !== "git") return;
42
+ const urlProperty = findPropertyWithKeyValue(properties, "url");
43
+ if (urlProperty?.value.type !== "JSONLiteral" || typeof urlProperty.value.value !== "string" || !isGitHubUrl(urlProperty.value.value)) return;
44
+ const url = urlProperty.value.value;
45
+ context.report({
46
+ fix(fixer) {
47
+ return fixer.replaceText(node.value, JSON.stringify(cleanGitHubUrl(url)));
48
+ },
49
+ messageId: "preferShorthand",
50
+ node: node.value
51
+ });
52
+ }
53
+ return { JSONProperty(node) {
54
+ if (node.key.type !== "JSONLiteral" || node.key.value !== "repository" || node.parent.parent.parent.type !== "Program") return;
55
+ if (form === "shorthand") validateRepositoryForShorthand(node);
56
+ else validateRepositoryForObject(node);
57
+ } };
58
+ },
59
+ meta: {
60
+ defaultOptions: [{ form: "object" }],
61
+ docs: {
62
+ category: "Best Practices",
63
+ description: "Enforce either object or shorthand declaration for repository.",
64
+ recommended: true
65
+ },
66
+ fixable: "code",
67
+ messages: {
68
+ preferObject: "Prefer an object locator for a repository.",
69
+ preferShorthand: "Prefer a shorthand locator for a GitHub repository."
70
+ },
71
+ schema: [{
72
+ additionalProperties: false,
73
+ properties: { form: {
74
+ description: "Specifies which repository form to enforce.",
75
+ enum: ["object", "shorthand"],
76
+ type: ["string"]
77
+ } },
78
+ type: "object"
79
+ }],
80
+ type: "suggestion"
81
+ },
82
+ name: "repository-shorthand"
116
83
  });
117
- export {
118
- rule
119
- };
84
+
85
+ //#endregion
86
+ export { rule };
@@ -1,15 +1,10 @@
1
- import * as eslint from 'eslint';
2
- import * as jsonc_eslint_parser from 'jsonc-eslint-parser';
3
- import { PackageJsonRuleContext } from '../createRule.js';
4
- import 'estree';
1
+ import { PackageJsonRuleModule } from "../createRule.js";
5
2
 
3
+ //#region src/rules/require-properties.d.ts
6
4
  declare const rules: {
7
- [k: string]: {
8
- create(context: PackageJsonRuleContext<[({
9
- ignorePrivate?: boolean;
10
- } | undefined)?]>): jsonc_eslint_parser.RuleListener;
11
- meta: eslint.Rule.RuleMetaData;
12
- };
5
+ [k: string]: PackageJsonRuleModule<[({
6
+ ignorePrivate?: boolean;
7
+ } | undefined)?]>;
13
8
  };
14
-
15
- export { rules };
9
+ //#endregion
10
+ export { rules };
@@ -1,29 +1,33 @@
1
- import {
2
- createSimpleRequirePropertyRule
3
- } from "../utils/createSimpleRequirePropertyRule.js";
1
+ import { createSimpleRequirePropertyRule } from "../utils/createSimpleRequirePropertyRule.js";
2
+
3
+ //#region src/rules/require-properties.ts
4
4
  const properties = [
5
- ["author"],
6
- ["bugs"],
7
- ["bundleDependencies"],
8
- ["dependencies"],
9
- ["description", { isRecommended: true }],
10
- ["devDependencies"],
11
- ["engines"],
12
- ["files"],
13
- ["keywords"],
14
- ["name", { ignorePrivateDefault: true, isRecommended: true }],
15
- ["optionalDependencies"],
16
- ["peerDependencies"],
17
- ["type", { isRecommended: true }],
18
- ["types"],
19
- ["version", { ignorePrivateDefault: true, isRecommended: true }]
5
+ ["author"],
6
+ ["bugs"],
7
+ ["bundleDependencies"],
8
+ ["dependencies"],
9
+ ["description", { isRecommended: true }],
10
+ ["devDependencies"],
11
+ ["engines"],
12
+ ["files"],
13
+ ["keywords"],
14
+ ["name", {
15
+ ignorePrivateDefault: true,
16
+ isRecommended: true
17
+ }],
18
+ ["optionalDependencies"],
19
+ ["peerDependencies"],
20
+ ["type", { isRecommended: true }],
21
+ ["types"],
22
+ ["version", {
23
+ ignorePrivateDefault: true,
24
+ isRecommended: true
25
+ }]
20
26
  ];
21
- const rules = Object.fromEntries(
22
- properties.map(([propertyName, options]) => [
23
- `require-${propertyName}`,
24
- createSimpleRequirePropertyRule(propertyName, options)
25
- ])
26
- );
27
- export {
28
- rules
29
- };
27
+ const rules = Object.fromEntries(properties.map(([propertyName, options]) => {
28
+ const { rule, ruleName } = createSimpleRequirePropertyRule(propertyName, options);
29
+ return [ruleName, rule];
30
+ }));
31
+
32
+ //#endregion
33
+ export { rules };
@@ -1,20 +1,15 @@
1
- import * as eslint from 'eslint';
2
- import * as jsonc_eslint_parser from 'jsonc-eslint-parser';
3
- import { PackageJsonRuleContext } from '../createRule.js';
4
- import 'estree';
1
+ import { PackageJsonRuleModule } from "../createRule.js";
5
2
 
3
+ //#region src/rules/restrict-dependency-ranges.d.ts
6
4
  interface Option {
7
- forDependencyTypes?: string[];
8
- forPackages?: string[];
9
- forVersions?: string;
10
- rangeType: RangeType | RangeType[];
5
+ forDependencyTypes?: string[];
6
+ forPackages?: string[];
7
+ forVersions?: string;
8
+ rangeType: RangeType | RangeType[];
11
9
  }
12
10
  type Options = [Option | Option[] | undefined];
13
11
  declare const RANGE_TYPES: readonly ["caret", "pin", "tilde"];
14
12
  type RangeType = (typeof RANGE_TYPES)[number];
15
- declare const rule: {
16
- create(context: PackageJsonRuleContext<Options>): jsonc_eslint_parser.RuleListener;
17
- meta: eslint.Rule.RuleMetaData;
18
- };
19
-
20
- export { rule };
13
+ declare const rule: PackageJsonRuleModule<Options>;
14
+ //#endregion
15
+ export { rule };