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,87 +1,63 @@
1
- import {
2
- fixRemoveArrayElement,
3
- fixRemoveObjectProperty
4
- } from "eslint-fix-utils";
5
1
  import { createRule } from "../createRule.js";
6
2
  import { isJSONStringLiteral, isNotNullish } from "../utils/predicates.js";
7
- const dependencyPropertyNames = /* @__PURE__ */ new Set([
8
- "bundledDependencies",
9
- "bundleDependencies",
10
- "dependencies",
11
- "devDependencies",
12
- "optionalDependencies",
13
- "overrides",
14
- "peerDependencies"
3
+ import { fixRemoveArrayElement, fixRemoveObjectProperty } from "eslint-fix-utils";
4
+
5
+ //#region src/rules/unique-dependencies.ts
6
+ const dependencyPropertyNames = new Set([
7
+ "bundledDependencies",
8
+ "bundleDependencies",
9
+ "dependencies",
10
+ "devDependencies",
11
+ "optionalDependencies",
12
+ "overrides",
13
+ "peerDependencies"
15
14
  ]);
16
15
  const rule = createRule({
17
- create(context) {
18
- function check(elements, getNodeToRemove) {
19
- const seen = /* @__PURE__ */ new Set();
20
- for (const element of elements.filter(isNotNullish).filter(isJSONStringLiteral).reverse()) {
21
- if (seen.has(element.value)) {
22
- report(element, elements);
23
- } else {
24
- seen.add(element.value);
25
- }
26
- }
27
- function report(node, elements2) {
28
- const removal = getNodeToRemove(node);
29
- context.report({
30
- messageId: "overridden",
31
- node,
32
- suggest: [
33
- {
34
- fix: removal.type === "JSONProperty" ? fixRemoveObjectProperty(
35
- context,
36
- removal
37
- ) : fixRemoveArrayElement(
38
- context,
39
- removal,
40
- elements2
41
- ),
42
- messageId: "remove"
43
- }
44
- ]
45
- });
46
- }
47
- }
48
- return {
49
- "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral]"(node) {
50
- if (!dependencyPropertyNames.has(node.key.value)) {
51
- return;
52
- }
53
- switch (node.value.type) {
54
- case "JSONArrayExpression":
55
- check(node.value.elements, (element) => element);
56
- break;
57
- case "JSONObjectExpression":
58
- check(
59
- node.value.properties.map(
60
- (property) => property.key
61
- ),
62
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
63
- (property) => property.parent
64
- );
65
- break;
66
- }
67
- }
68
- };
69
- },
70
- meta: {
71
- docs: {
72
- category: "Best Practices",
73
- description: "Checks a dependency isn't specified more than once (i.e. in `dependencies` and `devDependencies`)",
74
- recommended: true
75
- },
76
- hasSuggestions: true,
77
- messages: {
78
- overridden: "Package name is overridden by a duplicate listing later on.",
79
- remove: "Remove this redundant dependency listing."
80
- },
81
- schema: [],
82
- type: "suggestion"
83
- }
16
+ create(context) {
17
+ function check(elements, getNodeToRemove) {
18
+ const seen = /* @__PURE__ */ new Set();
19
+ for (const element of elements.filter(isNotNullish).filter(isJSONStringLiteral).reverse()) if (seen.has(element.value)) report(element, elements);
20
+ else seen.add(element.value);
21
+ function report(node, elements$1) {
22
+ const removal = getNodeToRemove(node);
23
+ context.report({
24
+ messageId: "overridden",
25
+ node,
26
+ suggest: [{
27
+ fix: removal.type === "JSONProperty" ? fixRemoveObjectProperty(context, removal) : fixRemoveArrayElement(context, removal, elements$1),
28
+ messageId: "remove"
29
+ }]
30
+ });
31
+ }
32
+ }
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;
42
+ }
43
+ } };
44
+ },
45
+ meta: {
46
+ docs: {
47
+ category: "Best Practices",
48
+ description: "Checks a dependency isn't specified more than once (i.e. in `dependencies` and `devDependencies`)",
49
+ recommended: true
50
+ },
51
+ hasSuggestions: true,
52
+ messages: {
53
+ overridden: "Package name is overridden by a duplicate listing later on.",
54
+ remove: "Remove this redundant dependency listing."
55
+ },
56
+ schema: [],
57
+ type: "suggestion"
58
+ },
59
+ name: "unique-dependencies"
84
60
  });
85
- export {
86
- rule
87
- };
61
+
62
+ //#endregion
63
+ export { rule };
@@ -1,14 +1,9 @@
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/valid-bin.d.ts
6
4
  type Options = [{
7
- enforceCase: boolean;
5
+ enforceCase: boolean;
8
6
  }?];
9
- declare const rule: {
10
- create(context: PackageJsonRuleContext<Options>): jsonc_eslint_parser.RuleListener;
11
- meta: eslint.Rule.RuleMetaData;
12
- };
13
-
14
- export { rule };
7
+ declare const rule: PackageJsonRuleModule<Options>;
8
+ //#endregion
9
+ export { rule };
@@ -1,82 +1,63 @@
1
- import { kebabCase } from "change-case";
2
- import { validateBin } from "package-json-validator";
3
1
  import { createRule } from "../createRule.js";
4
2
  import { formatErrors } from "../utils/formatErrors.js";
3
+ import { kebabCase } from "change-case";
4
+ import { validateBin } from "package-json-validator";
5
+
6
+ //#region src/rules/valid-bin.ts
5
7
  const rule = createRule({
6
- create(context) {
7
- const shouldEnforceCase = !!context.options[0]?.enforceCase;
8
- return {
9
- "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=bin]"(node) {
10
- const binValueNode = node.value;
11
- const binValue = JSON.parse(
12
- context.sourceCode.getText(binValueNode)
13
- );
14
- const errors = validateBin(binValue);
15
- if (errors.length) {
16
- context.report({
17
- data: {
18
- errors: formatErrors(errors)
19
- },
20
- messageId: "validationError",
21
- node: binValueNode
22
- });
23
- }
24
- if (shouldEnforceCase && node.value.type === "JSONObjectExpression") {
25
- for (const property of node.value.properties) {
26
- const key = property.key;
27
- const kebabCaseKey = kebabCase(key.value);
28
- if (kebabCaseKey !== key.value) {
29
- context.report({
30
- data: {
31
- property: key.value
32
- },
33
- messageId: "invalidCase",
34
- node: key,
35
- suggest: [
36
- {
37
- fix: (fixer) => {
38
- return fixer.replaceText(
39
- key,
40
- JSON.stringify(kebabCaseKey)
41
- );
42
- },
43
- messageId: "convertToKebabCase"
44
- }
45
- ]
46
- });
47
- }
48
- }
49
- }
50
- }
51
- };
52
- },
53
- meta: {
54
- docs: {
55
- category: "Best Practices",
56
- description: "Enforce that the `bin` property is valid.",
57
- recommended: true
58
- },
59
- hasSuggestions: true,
60
- messages: {
61
- convertToKebabCase: "Convert command name to kebab case.",
62
- invalidCase: "Command name {{ property }} should be in kebab case.",
63
- validationError: "Invalid bin: {{ errors }}"
64
- },
65
- schema: [
66
- {
67
- additionalProperties: false,
68
- properties: {
69
- enforceCase: {
70
- default: false,
71
- type: "boolean"
72
- }
73
- },
74
- type: "object"
75
- }
76
- ],
77
- type: "problem"
78
- }
8
+ create(context) {
9
+ const shouldEnforceCase = !!context.options[0]?.enforceCase;
10
+ return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=bin]"(node) {
11
+ const binValueNode = node.value;
12
+ const binValue = JSON.parse(context.sourceCode.getText(binValueNode));
13
+ const errors = validateBin(binValue);
14
+ if (errors.length) context.report({
15
+ data: { errors: formatErrors(errors) },
16
+ messageId: "validationError",
17
+ node: binValueNode
18
+ });
19
+ if (shouldEnforceCase && node.value.type === "JSONObjectExpression") for (const property of node.value.properties) {
20
+ const key = property.key;
21
+ const kebabCaseKey = kebabCase(key.value);
22
+ if (kebabCaseKey !== key.value) context.report({
23
+ data: { property: key.value },
24
+ messageId: "invalidCase",
25
+ node: key,
26
+ suggest: [{
27
+ fix: (fixer) => {
28
+ return fixer.replaceText(key, JSON.stringify(kebabCaseKey));
29
+ },
30
+ messageId: "convertToKebabCase"
31
+ }]
32
+ });
33
+ }
34
+ } };
35
+ },
36
+ meta: {
37
+ defaultOptions: [{ enforceCase: false }],
38
+ docs: {
39
+ category: "Best Practices",
40
+ description: "Enforce that the `bin` property is valid.",
41
+ recommended: true
42
+ },
43
+ hasSuggestions: true,
44
+ messages: {
45
+ convertToKebabCase: "Convert command name to kebab case.",
46
+ invalidCase: "Command name {{ property }} should be in kebab case.",
47
+ validationError: "Invalid bin: {{ errors }}"
48
+ },
49
+ schema: [{
50
+ additionalProperties: false,
51
+ properties: { enforceCase: {
52
+ description: "Enforce that the bin's keys should be in kebab case.",
53
+ type: "boolean"
54
+ } },
55
+ type: "object"
56
+ }],
57
+ type: "problem"
58
+ },
59
+ name: "valid-bin"
79
60
  });
80
- export {
81
- rule
82
- };
61
+
62
+ //#endregion
63
+ export { rule };
@@ -1,11 +1,6 @@
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
 
6
- declare const rule: {
7
- create(context: PackageJsonRuleContext<unknown[]>): jsonc_eslint_parser.RuleListener;
8
- meta: eslint.Rule.RuleMetaData;
9
- };
10
-
11
- export { rule };
3
+ //#region src/rules/valid-local-dependency.d.ts
4
+ declare const rule: PackageJsonRuleModule<unknown[]>;
5
+ //#endregion
6
+ export { rule };
@@ -1,62 +1,54 @@
1
- import path from "path";
2
1
  import { createRule } from "../createRule.js";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+
5
+ //#region src/rules/valid-local-dependency.ts
6
+ const require = createRequire(import.meta.url);
3
7
  const fileRegex = /^file:/;
4
8
  const linkRegex = /^link:/;
5
9
  const rule = createRule({
6
- create(context) {
7
- return {
8
- "Program:exit"() {
9
- const original = JSON.parse(context.sourceCode.text);
10
- const { dependencies, devDependencies, peerDependencies } = original;
11
- const depObjs = [
12
- Object.entries(dependencies ?? {}),
13
- Object.entries(peerDependencies ?? {}),
14
- Object.entries(devDependencies ?? {})
15
- ];
16
- for (const obj of depObjs) {
17
- for (const [key, value] of obj) {
18
- const response = (pathToken) => {
19
- const filePath = path.join(
20
- context.filename.replace("package.json", ""),
21
- value.replace(pathToken, "")
22
- );
23
- try {
24
- require.resolve(filePath);
25
- } catch {
26
- context.report({
27
- data: {
28
- package: key,
29
- path: value
30
- },
31
- messageId: "invalidPath",
32
- node: context.sourceCode.ast
33
- });
34
- }
35
- };
36
- if (value.startsWith("link:")) {
37
- response(linkRegex);
38
- }
39
- if (value.startsWith("file:")) {
40
- response(fileRegex);
41
- }
42
- }
43
- }
44
- }
45
- };
46
- },
47
- meta: {
48
- deprecated: true,
49
- docs: {
50
- category: "Best Practices",
51
- description: "Checks existence of local dependencies in the package.json"
52
- },
53
- messages: {
54
- invalidPath: "The package {{package}} does not exist given the specified path: {{path}}."
55
- },
56
- schema: [],
57
- type: "problem"
58
- }
10
+ create(context) {
11
+ return { "Program:exit"() {
12
+ const original = JSON.parse(context.sourceCode.text);
13
+ const { dependencies, devDependencies, peerDependencies } = original;
14
+ const depObjs = [
15
+ Object.entries(dependencies ?? {}),
16
+ Object.entries(peerDependencies ?? {}),
17
+ Object.entries(devDependencies ?? {})
18
+ ];
19
+ for (const obj of depObjs) for (const [key, value] of obj) {
20
+ const response = (pathToken) => {
21
+ const filePath = path.join(context.filename.replace("package.json", ""), value.replace(pathToken, ""));
22
+ try {
23
+ require.resolve(filePath);
24
+ } catch {
25
+ context.report({
26
+ data: {
27
+ package: key,
28
+ path: value
29
+ },
30
+ messageId: "invalidPath",
31
+ node: context.sourceCode.ast
32
+ });
33
+ }
34
+ };
35
+ if (value.startsWith("link:")) response(linkRegex);
36
+ if (value.startsWith("file:")) response(fileRegex);
37
+ }
38
+ } };
39
+ },
40
+ meta: {
41
+ deprecated: true,
42
+ docs: {
43
+ category: "Best Practices",
44
+ description: "Checks existence of local dependencies in the package.json"
45
+ },
46
+ messages: { invalidPath: "The package {{package}} does not exist given the specified path: {{path}}." },
47
+ schema: [],
48
+ type: "problem"
49
+ },
50
+ name: "valid-local-dependency"
59
51
  });
60
- export {
61
- rule
62
- };
52
+
53
+ //#endregion
54
+ export { rule };
@@ -1,11 +1,6 @@
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
 
6
- declare const rule: {
7
- create(context: PackageJsonRuleContext<unknown[]>): jsonc_eslint_parser.RuleListener;
8
- meta: eslint.Rule.RuleMetaData;
9
- };
10
-
11
- export { rule };
3
+ //#region src/rules/valid-name.d.ts
4
+ declare const rule: PackageJsonRuleModule<unknown[]>;
5
+ //#endregion
6
+ export { rule };
@@ -1,51 +1,44 @@
1
- import validate from "validate-npm-package-name";
2
1
  import { createRule } from "../createRule.js";
2
+ import validate from "validate-npm-package-name";
3
+
4
+ //#region src/rules/valid-name.ts
3
5
  const rule = createRule({
4
- create(context) {
5
- return {
6
- "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=name]"(node) {
7
- if (node.value.type !== "JSONLiteral" || typeof node.value.value !== "string") {
8
- context.report({
9
- messageId: "type",
10
- node: node.value
11
- });
12
- return;
13
- }
14
- const privateField = node.parent.properties.find(
15
- (p) => p.key.type === "JSONLiteral" && p.key.value === "private"
16
- );
17
- if (privateField && privateField.value.type === "JSONLiteral" && (privateField.value.value === true || privateField.value.value === "true")) {
18
- return;
19
- }
20
- const { errors, warnings } = validate(node.value.value);
21
- const complaints = [...errors ?? [], ...warnings ?? []];
22
- if (!complaints.length) {
23
- return;
24
- }
25
- context.report({
26
- data: {
27
- complaints: complaints.map((error) => error.substring(0, error.length)).join("; ")
28
- },
29
- messageId: "invalid",
30
- node: node.value
31
- });
32
- }
33
- };
34
- },
35
- meta: {
36
- docs: {
37
- category: "Best Practices",
38
- description: "Enforce that package names are valid npm package names",
39
- recommended: true
40
- },
41
- messages: {
42
- invalid: "Invalid npm package name: {{ complaints }}.",
43
- type: '"name" should be a string.'
44
- },
45
- schema: [],
46
- type: "problem"
47
- }
6
+ create(context) {
7
+ return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=name]"(node) {
8
+ if (node.value.type !== "JSONLiteral" || typeof node.value.value !== "string") {
9
+ context.report({
10
+ messageId: "type",
11
+ node: node.value
12
+ });
13
+ return;
14
+ }
15
+ const privateField = node.parent.properties.find((p) => p.key.type === "JSONLiteral" && p.key.value === "private");
16
+ if (privateField && privateField.value.type === "JSONLiteral" && (privateField.value.value === true || privateField.value.value === "true")) return;
17
+ const { errors, warnings } = validate(node.value.value);
18
+ const complaints = [...errors ?? [], ...warnings ?? []];
19
+ if (!complaints.length) return;
20
+ context.report({
21
+ data: { complaints: complaints.map((error) => error.substring(0, error.length)).join("; ") },
22
+ messageId: "invalid",
23
+ node: node.value
24
+ });
25
+ } };
26
+ },
27
+ meta: {
28
+ docs: {
29
+ category: "Best Practices",
30
+ description: "Enforce that package names are valid npm package names",
31
+ recommended: true
32
+ },
33
+ messages: {
34
+ invalid: "Invalid npm package name: {{ complaints }}.",
35
+ type: "\"name\" should be a string."
36
+ },
37
+ schema: [],
38
+ type: "problem"
39
+ },
40
+ name: "valid-name"
48
41
  });
49
- export {
50
- rule
51
- };
42
+
43
+ //#endregion
44
+ 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/valid-package-definition.d.ts
6
4
  interface Option {
7
- ignoreProperties?: string[];
5
+ ignoreProperties?: string[];
8
6
  }
9
7
  type Options = [Option?];
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 };