-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(require-author): add new
require-author
rule (#851)
<!-- π Hi, thanks for sending a PR to eslint-plugin-package-json! π. Please fill out all fields below and make sure each item is true and [x] checked. Otherwise we may not be able to review your PR. --> ## PR Checklist - [x] Addresses an existing open issue: fixes #795 - [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22) - [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/blob/main/.github/CONTRIBUTING.md) were taken ## Overview This change adds the first or our new `require-` rules, and creates some foundational plumbing to make it super easy to add new require rules. I've only done author in this PR. Assuming this all looks good, we can quickly knock all the rest of the require rules in one shot.
- Loading branch information
1 parent
f4666be
commit cde68da
Showing
7 changed files
with
153 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# require-author | ||
|
||
<!-- end auto-generated rule header --> | ||
|
||
This rule checks for the existence of the `"author"` property in a package.json, | ||
and reports a violation if it doesn't exist. | ||
|
||
Example of **incorrect** code for this rule: | ||
|
||
```json | ||
{ | ||
"name": "thee-silver-mt-zion", | ||
"version": "13.0.0" | ||
} | ||
``` | ||
|
||
Example of **correct** code for this rule: | ||
|
||
```json | ||
{ | ||
"name": "thee-silver-mt-zion", | ||
"version": "13.0.0", | ||
"author": "Jessica Moss" | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import type { PackageJsonRuleModule } from "../createRule.js"; | ||
|
||
import { createRequirePropertyRule } from "../utils/createRequirePropertyRule.js"; | ||
|
||
// List of all properties we want to create require- rules for, | ||
// in the format [propertyName, isRecommended] | ||
const properties = [ | ||
["author", false], | ||
// TODO: More to come! | ||
] satisfies [string, boolean][]; | ||
|
||
/** All require- flavor rules */ | ||
export const rules = properties.reduce<Record<string, PackageJsonRuleModule>>( | ||
(acc, [propertyName, isRecommended]) => { | ||
acc[`require-${propertyName}`] = createRequirePropertyRule( | ||
propertyName, | ||
isRecommended, | ||
); | ||
return acc; | ||
}, | ||
{}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { rules } from "../../rules/require-properties.js"; | ||
import { ruleTester } from "./ruleTester.js"; | ||
|
||
ruleTester.run("require-author", rules["require-author"], { | ||
invalid: [ | ||
{ | ||
code: "{}", | ||
errors: [ | ||
{ | ||
data: { property: "author" }, | ||
line: 1, | ||
messageId: "missing", | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `{ | ||
"name": "foo", | ||
"version": "1.0.0" | ||
} | ||
`, | ||
errors: [ | ||
{ | ||
data: { property: "author" }, | ||
line: 1, | ||
messageId: "missing", | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `{ | ||
"name": "foo", | ||
"version": "1.0.0", | ||
"bin": { | ||
"author": "./cli.js" | ||
} | ||
} | ||
`, | ||
errors: [ | ||
{ | ||
data: { property: "author" }, | ||
line: 1, | ||
messageId: "missing", | ||
}, | ||
], | ||
}, | ||
], | ||
valid: [ | ||
`{ "main": "./index.js", "author": "Sophie Trudeau" }`, | ||
`{ "author": "Jessica Moss" }`, | ||
`{ "author": 123 }`, | ||
`{ "author": { "name": "Jessica Moss" } }`, | ||
], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import type { AST as JsonAST } from "jsonc-eslint-parser"; | ||
|
||
import { createRule } from "../createRule.js"; | ||
import { isJSONStringLiteral } from "./predicates.js"; | ||
|
||
/** | ||
* Given a top-level property name, create a rule that requires that property to be present. | ||
* Optionally, include it in the recommended config. | ||
*/ | ||
export const createRequirePropertyRule = ( | ||
propertyName: string, | ||
isRecommended = false, | ||
) => { | ||
return createRule({ | ||
create(context) { | ||
return { | ||
"Program > JSONExpressionStatement > JSONObjectExpression"( | ||
node: JsonAST.JSONObjectExpression, | ||
) { | ||
if ( | ||
!node.properties.some( | ||
(property) => | ||
isJSONStringLiteral(property.key) && | ||
property.key.value === propertyName, | ||
) | ||
) { | ||
context.report({ | ||
data: { property: propertyName }, | ||
messageId: "missing", | ||
node: context.sourceCode.ast, | ||
}); | ||
} | ||
}, | ||
}; | ||
}, | ||
meta: { | ||
docs: { | ||
description: `Requires the \`${propertyName}\` property to be present.`, | ||
recommended: isRecommended, | ||
}, | ||
messages: { | ||
missing: "Property '{{property}}' is required.", | ||
}, | ||
schema: [], | ||
type: "suggestion", | ||
}, | ||
}); | ||
}; |