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,56 +1,47 @@
1
- import { validate } from "package-json-validator";
2
1
  import { createRule } from "../createRule.js";
2
+ import { validate } from "package-json-validator";
3
+
4
+ //#region src/rules/valid-package-definition.ts
3
5
  const ignoredErrors = [
4
- /^Url not valid/i,
5
- /^Invalid version range for .+?: file:/i,
6
- /^author field should have name/i
6
+ /^Url not valid/i,
7
+ /^Invalid version range for .+?: file:/i,
8
+ /^author field should have name/i
7
9
  ];
8
10
  const isUsableError = (errorText) => ignoredErrors.every((pattern) => !pattern.test(errorText));
9
11
  const rule = createRule({
10
- create(context) {
11
- const ignoreProperties = context.options[0]?.ignoreProperties ?? [];
12
- return {
13
- "Program:exit"() {
14
- const validation = validate(context.sourceCode.text);
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) {
20
- context.report({
21
- // eslint-disable-next-line eslint-plugin/prefer-message-ids
22
- message: error.message,
23
- node: context.sourceCode.ast
24
- });
25
- }
26
- }
27
- }
28
- };
29
- },
30
- // eslint-disable-next-line eslint-plugin/prefer-message-ids
31
- meta: {
32
- docs: {
33
- category: "Best Practices",
34
- description: "Enforce that package.json has all properties required by the npm spec",
35
- recommended: true
36
- },
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
- ],
51
- type: "problem"
52
- }
12
+ create(context) {
13
+ const ignoreProperties = context.options[0]?.ignoreProperties ?? [];
14
+ return { "Program:exit"() {
15
+ const validation = validate(context.sourceCode.text);
16
+ const usableErrors = validation.errors?.filter((error) => {
17
+ return isUsableError(error.message) && !ignoreProperties.includes(error.field);
18
+ }) ?? [];
19
+ for (const error of usableErrors) if (error.message) context.report({
20
+ message: error.message,
21
+ node: context.sourceCode.ast
22
+ });
23
+ } };
24
+ },
25
+ meta: {
26
+ defaultOptions: [{ ignoreProperties: [] }],
27
+ docs: {
28
+ category: "Best Practices",
29
+ description: "Enforce that package.json has all properties required by the npm spec",
30
+ recommended: true
31
+ },
32
+ schema: [{
33
+ additionalProperties: false,
34
+ properties: { ignoreProperties: {
35
+ description: "Array of top-level package properties to ignore.",
36
+ items: { type: "string" },
37
+ type: "array"
38
+ } },
39
+ type: "object"
40
+ }],
41
+ type: "problem"
42
+ },
43
+ name: "valid-package-definition"
53
44
  });
54
- export {
55
- rule
56
- };
45
+
46
+ //#endregion
47
+ export { rule };
@@ -1,9 +1,9 @@
1
- import { PackageJsonRuleModule } from '../createRule.js';
2
- import 'estree';
3
- import 'eslint';
4
- import 'jsonc-eslint-parser';
1
+ import { PackageJsonRuleModule } from "../createRule.js";
5
2
 
3
+ //#region src/rules/valid-properties.d.ts
6
4
  /** All basic valid- flavor rules */
7
- declare const rules: Record<string, PackageJsonRuleModule<unknown[]>>;
8
-
9
- export { rules };
5
+ declare const rules: {
6
+ [k: string]: PackageJsonRuleModule<unknown[]>;
7
+ };
8
+ //#endregion
9
+ export { rules };
@@ -1,57 +1,35 @@
1
- import {
2
- validateAuthor,
3
- validateBundleDependencies,
4
- validateConfig,
5
- validateCpu,
6
- validateDependencies,
7
- validateDescription,
8
- validateLicense,
9
- validateScripts,
10
- validateType
11
- } from "package-json-validator";
12
- import {
13
- createSimpleValidPropertyRule
14
- } from "../utils/createSimpleValidPropertyRule.js";
1
+ import { createSimpleValidPropertyRule } from "../utils/createSimpleValidPropertyRule.js";
2
+ import { validateAuthor, validateBundleDependencies, validateConfig, validateCpu, validateDependencies, validateDescription, validateLicense, validateScripts, validateType } from "package-json-validator";
3
+
4
+ //#region src/rules/valid-properties.ts
15
5
  const properties = [
16
- ["author", validateAuthor],
17
- [
18
- "bundleDependencies",
19
- {
20
- aliases: ["bundledDependencies"],
21
- validator: validateBundleDependencies
22
- }
23
- ],
24
- ["config", validateConfig],
25
- ["cpu", validateCpu],
26
- ["dependencies", validateDependencies],
27
- ["description", validateDescription],
28
- ["devDependencies", validateDependencies],
29
- ["license", validateLicense],
30
- ["optionalDependencies", validateDependencies],
31
- ["peerDependencies", validateDependencies],
32
- ["scripts", validateScripts],
33
- ["type", validateType]
34
- // TODO: More to come!
6
+ ["author", validateAuthor],
7
+ ["bundleDependencies", {
8
+ aliases: ["bundledDependencies"],
9
+ validator: validateBundleDependencies
10
+ }],
11
+ ["config", validateConfig],
12
+ ["cpu", validateCpu],
13
+ ["dependencies", validateDependencies],
14
+ ["description", validateDescription],
15
+ ["devDependencies", validateDependencies],
16
+ ["license", validateLicense],
17
+ ["optionalDependencies", validateDependencies],
18
+ ["peerDependencies", validateDependencies],
19
+ ["scripts", validateScripts],
20
+ ["type", validateType]
35
21
  ];
36
- const rules = properties.reduce(
37
- (acc, [propertyName, validationFunctionOrOptions]) => {
38
- let validationFunction;
39
- let aliases = [];
40
- if (typeof validationFunctionOrOptions === "object") {
41
- validationFunction = validationFunctionOrOptions.validator;
42
- aliases = validationFunctionOrOptions.aliases;
43
- } else {
44
- validationFunction = validationFunctionOrOptions;
45
- }
46
- acc[`valid-${propertyName}`] = createSimpleValidPropertyRule(
47
- propertyName,
48
- validationFunction,
49
- aliases
50
- );
51
- return acc;
52
- },
53
- {}
54
- );
55
- export {
56
- rules
57
- };
22
+ /** All basic valid- flavor rules */
23
+ const rules = Object.fromEntries(properties.map(([propertyName, validationFunctionOrOptions]) => {
24
+ let validationFunction;
25
+ let aliases = [];
26
+ if (typeof validationFunctionOrOptions === "object") {
27
+ validationFunction = validationFunctionOrOptions.validator;
28
+ aliases = validationFunctionOrOptions.aliases;
29
+ } else validationFunction = validationFunctionOrOptions;
30
+ const { rule, ruleName } = createSimpleValidPropertyRule(propertyName, validationFunction, aliases);
31
+ return [ruleName, rule];
32
+ }));
33
+
34
+ //#endregion
35
+ export { rules };
@@ -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-repository-directory.d.ts
4
+ declare const rule: PackageJsonRuleModule<unknown[]>;
5
+ //#endregion
6
+ export { rule };
@@ -1,86 +1,71 @@
1
- import { findRootSync } from "@altano/repository-tools";
2
- import * as path from "node:path";
3
- import { sep as posixSep } from "node:path/posix";
4
1
  import { createRule } from "../createRule.js";
5
2
  import { findPropertyWithKeyValue } from "../utils/findPropertyWithKeyValue.js";
3
+ import * as path$1 from "node:path";
4
+ import { findRootSync } from "@altano/repository-tools";
5
+ import { sep } from "node:path/posix";
6
+
7
+ //#region src/rules/valid-repository-directory.ts
8
+ /**
9
+ * Checks if the child path appears at the end of the parent path.
10
+ * @example '/a/b/c', 'c' => true
11
+ * @example '/a/b/c', 'b/c' => true
12
+ * @example '/a/b/c', 'b' => false
13
+ * @example '/a/b/c', 'd' => false
14
+ */
6
15
  function pathEndsWith(parent, child) {
7
- const segments = parent.split(path.sep);
8
- if (parent === child) {
9
- return true;
10
- }
11
- let pathToCheck = "";
12
- return segments.reverse().some((segment) => {
13
- pathToCheck = path.join(segment, pathToCheck);
14
- if (pathToCheck === child) {
15
- return true;
16
- }
17
- });
16
+ const segments = parent.split(path$1.sep);
17
+ if (parent === child) return true;
18
+ let pathToCheck = "";
19
+ return segments.reverse().some((segment) => {
20
+ pathToCheck = path$1.join(segment, pathToCheck);
21
+ if (pathToCheck === child) return true;
22
+ });
18
23
  }
19
24
  const rule = createRule({
20
- create(context) {
21
- return {
22
- "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=repository][value.type=JSONObjectExpression]"(node) {
23
- const directoryProperty = findPropertyWithKeyValue(
24
- node.value.properties,
25
- "directory"
26
- );
27
- if (directoryProperty?.value.type !== "JSONLiteral" || typeof directoryProperty.value.value !== "string") {
28
- return;
29
- }
30
- const directoryValue = directoryProperty.value.value;
31
- const fileDirectory = path.normalize(
32
- path.dirname(context.filename)
33
- );
34
- const repositoryRoot = findRootSync(fileDirectory);
35
- if (repositoryRoot == null) {
36
- if (!pathEndsWith(
37
- fileDirectory,
38
- path.normalize(directoryValue)
39
- )) {
40
- context.report({
41
- messageId: "mismatched",
42
- node: directoryProperty.value
43
- });
44
- }
45
- } else {
46
- const expected = path.relative(repositoryRoot, fileDirectory).replaceAll(path.sep, posixSep);
47
- if (expected !== directoryValue) {
48
- context.report({
49
- messageId: "mismatched",
50
- node: directoryProperty.value,
51
- suggest: [
52
- {
53
- data: { expected },
54
- fix(fixer) {
55
- return fixer.replaceText(
56
- directoryProperty.value,
57
- `"${expected}"`
58
- );
59
- },
60
- messageId: "replace"
61
- }
62
- ]
63
- });
64
- }
65
- }
66
- }
67
- };
68
- },
69
- meta: {
70
- docs: {
71
- category: "Best Practices",
72
- description: "Enforce that if repository directory is specified, it matches the path to the package.json file",
73
- recommended: true
74
- },
75
- hasSuggestions: true,
76
- messages: {
77
- mismatched: "Directory does not match package.json directory.",
78
- replace: "Replace with '{{ expected }}'."
79
- },
80
- schema: [],
81
- type: "suggestion"
82
- }
25
+ create(context) {
26
+ return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=repository][value.type=JSONObjectExpression]"(node) {
27
+ const directoryProperty = findPropertyWithKeyValue(node.value.properties, "directory");
28
+ if (directoryProperty?.value.type !== "JSONLiteral" || typeof directoryProperty.value.value !== "string") return;
29
+ const directoryValue = directoryProperty.value.value;
30
+ const fileDirectory = path$1.normalize(path$1.dirname(context.filename));
31
+ const repositoryRoot = findRootSync(fileDirectory);
32
+ if (repositoryRoot == null) {
33
+ if (!pathEndsWith(fileDirectory, path$1.normalize(directoryValue))) context.report({
34
+ messageId: "mismatched",
35
+ node: directoryProperty.value
36
+ });
37
+ } else {
38
+ const expected = path$1.relative(repositoryRoot, fileDirectory).replaceAll(path$1.sep, sep);
39
+ if (expected !== directoryValue) context.report({
40
+ messageId: "mismatched",
41
+ node: directoryProperty.value,
42
+ suggest: [{
43
+ data: { expected },
44
+ fix(fixer) {
45
+ return fixer.replaceText(directoryProperty.value, `"${expected}"`);
46
+ },
47
+ messageId: "replace"
48
+ }]
49
+ });
50
+ }
51
+ } };
52
+ },
53
+ meta: {
54
+ docs: {
55
+ category: "Best Practices",
56
+ description: "Enforce that if repository directory is specified, it matches the path to the package.json file",
57
+ recommended: true
58
+ },
59
+ hasSuggestions: true,
60
+ messages: {
61
+ mismatched: "Directory does not match package.json directory.",
62
+ replace: "Replace with '{{ expected }}'."
63
+ },
64
+ schema: [],
65
+ type: "suggestion"
66
+ },
67
+ name: "valid-repository-directory"
83
68
  });
84
- export {
85
- rule
86
- };
69
+
70
+ //#endregion
71
+ 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-version.d.ts
4
+ declare const rule: PackageJsonRuleModule<unknown[]>;
5
+ //#endregion
6
+ export { rule };
@@ -1,39 +1,38 @@
1
- import semver from "semver";
2
1
  import { createRule } from "../createRule.js";
2
+ import semver from "semver";
3
+
4
+ //#region src/rules/valid-version.ts
3
5
  const rule = createRule({
4
- create(context) {
5
- return {
6
- "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=version]"(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
- if (!semver.valid(node.value.value)) {
15
- context.report({
16
- messageId: "invalid",
17
- node: node.value
18
- });
19
- }
20
- }
21
- };
22
- },
23
- meta: {
24
- docs: {
25
- category: "Best Practices",
26
- description: "Enforce that package versions are valid semver specifiers",
27
- recommended: true
28
- },
29
- messages: {
30
- invalid: "Version is not a valid semver specifier.",
31
- type: '"version" should be a string.'
32
- },
33
- schema: [],
34
- type: "problem"
35
- }
6
+ create(context) {
7
+ return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=version]"(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
+ if (!semver.valid(node.value.value)) context.report({
16
+ messageId: "invalid",
17
+ node: node.value
18
+ });
19
+ } };
20
+ },
21
+ meta: {
22
+ docs: {
23
+ category: "Best Practices",
24
+ description: "Enforce that package versions are valid semver specifiers",
25
+ recommended: true
26
+ },
27
+ messages: {
28
+ invalid: "Version is not a valid semver specifier.",
29
+ type: "\"version\" should be a string."
30
+ },
31
+ schema: [],
32
+ type: "problem"
33
+ },
34
+ name: "valid-version"
36
35
  });
37
- export {
38
- rule
39
- };
36
+
37
+ //#endregion
38
+ export { rule };
@@ -0,0 +1,8 @@
1
+ import { JSONNode } from "jsonc-eslint-parser";
2
+
3
+ //#region src/types/estree.d.ts
4
+ declare module "estree" {
5
+ interface NodeMap {
6
+ JSONNode: JSONNode;
7
+ }
8
+ }
@@ -1,20 +1,18 @@
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/utils/createSimpleRequirePropertyRule.d.ts
6
4
  interface CreateRequirePropertyRuleOptions {
7
- /**
8
- * The default value of `ignorePrivate` rule option.
9
- */
10
- ignorePrivateDefault?: boolean;
11
- /**
12
- * Whether the rule should be included in the recommended config.
13
- */
14
- isRecommended?: boolean;
5
+ /**
6
+ * The default value of `ignorePrivate` rule option.
7
+ */
8
+ ignorePrivateDefault?: boolean;
9
+ /**
10
+ * Whether the rule should be included in the recommended config.
11
+ */
12
+ isRecommended?: boolean;
15
13
  }
16
14
  type Options = [{
17
- ignorePrivate?: boolean;
15
+ ignorePrivate?: boolean;
18
16
  }?];
19
17
  /**
20
18
  * Given a top-level property name, create a rule that requires that property to be present.
@@ -22,9 +20,12 @@ type Options = [{
22
20
  * Note: this will only create a basic require rule, with no options. If you need
23
21
  * to create a more complex rule, create it in its own file.
24
22
  */
25
- declare const createSimpleRequirePropertyRule: (propertyName: string, { ignorePrivateDefault, isRecommended, }?: CreateRequirePropertyRuleOptions) => {
26
- create(context: PackageJsonRuleContext<Options>): jsonc_eslint_parser.RuleListener;
27
- meta: eslint.Rule.RuleMetaData;
23
+ declare const createSimpleRequirePropertyRule: (propertyName: string, {
24
+ ignorePrivateDefault,
25
+ isRecommended
26
+ }?: CreateRequirePropertyRuleOptions) => {
27
+ rule: PackageJsonRuleModule<Options>;
28
+ ruleName: string;
28
29
  };
29
-
30
- export { type CreateRequirePropertyRuleOptions, createSimpleRequirePropertyRule };
30
+ //#endregion
31
+ export { CreateRequirePropertyRuleOptions, createSimpleRequirePropertyRule };
@@ -1,56 +1,51 @@
1
1
  import { createRule } from "../createRule.js";
2
2
  import { isJSONStringLiteral } from "./predicates.js";
3
- const createSimpleRequirePropertyRule = (propertyName, {
4
- ignorePrivateDefault = false,
5
- isRecommended
6
- } = {}) => {
7
- return createRule({
8
- create(context) {
9
- const enforceForPrivate = context.settings.packageJson?.enforceForPrivate;
10
- const ignorePrivate = context.options[0]?.ignorePrivate ?? (typeof enforceForPrivate === "boolean" ? !enforceForPrivate : ignorePrivateDefault);
11
- return {
12
- "Program > JSONExpressionStatement > JSONObjectExpression"(node) {
13
- if (ignorePrivate && node.properties.some(
14
- (property) => isJSONStringLiteral(property.key) && property.key.value === "private" && property.value.type === "JSONLiteral" && property.value.value === true
15
- )) {
16
- return;
17
- }
18
- if (!node.properties.some(
19
- (property) => isJSONStringLiteral(property.key) && property.key.value === propertyName
20
- )) {
21
- context.report({
22
- data: { property: propertyName },
23
- messageId: "missing",
24
- node: context.sourceCode.ast
25
- });
26
- }
27
- }
28
- };
29
- },
30
- meta: {
31
- docs: {
32
- description: `Requires the \`${propertyName}\` property to be present.`,
33
- recommended: isRecommended
34
- },
35
- messages: {
36
- missing: "Property '{{property}}' is required."
37
- },
38
- schema: [
39
- {
40
- additionalProperties: false,
41
- properties: {
42
- ignorePrivate: {
43
- default: ignorePrivateDefault,
44
- type: "boolean"
45
- }
46
- },
47
- type: "object"
48
- }
49
- ],
50
- type: "suggestion"
51
- }
52
- });
53
- };
54
- export {
55
- createSimpleRequirePropertyRule
3
+
4
+ //#region src/utils/createSimpleRequirePropertyRule.ts
5
+ /**
6
+ * Given a top-level property name, create a rule that requires that property to be present.
7
+ * Optionally, include it in the recommended config.
8
+ * Note: this will only create a basic require rule, with no options. If you need
9
+ * to create a more complex rule, create it in its own file.
10
+ */
11
+ const createSimpleRequirePropertyRule = (propertyName, { ignorePrivateDefault = false, isRecommended } = {}) => {
12
+ const ruleName = `require-${propertyName}`;
13
+ const rule = createRule({
14
+ create(context) {
15
+ const enforceForPrivate = context.settings.packageJson?.enforceForPrivate;
16
+ const ignorePrivate = context.options[0]?.ignorePrivate ?? (typeof enforceForPrivate === "boolean" ? !enforceForPrivate : ignorePrivateDefault);
17
+ return { "Program > JSONExpressionStatement > JSONObjectExpression"(node) {
18
+ if (ignorePrivate && node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === "private" && property.value.type === "JSONLiteral" && property.value.value === true)) return;
19
+ if (!node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === propertyName)) context.report({
20
+ data: { property: propertyName },
21
+ messageId: "missing",
22
+ node: context.sourceCode.ast
23
+ });
24
+ } };
25
+ },
26
+ meta: {
27
+ docs: {
28
+ description: `Requires the \`${propertyName}\` property to be present.`,
29
+ recommended: isRecommended
30
+ },
31
+ messages: { missing: "Property '{{property}}' is required." },
32
+ schema: [{
33
+ additionalProperties: false,
34
+ properties: { ignorePrivate: {
35
+ default: ignorePrivateDefault,
36
+ type: "boolean"
37
+ } },
38
+ type: "object"
39
+ }],
40
+ type: "suggestion"
41
+ },
42
+ name: ruleName
43
+ });
44
+ return {
45
+ rule,
46
+ ruleName
47
+ };
56
48
  };
49
+
50
+ //#endregion
51
+ export { createSimpleRequirePropertyRule };