Skip to content

Commit

Permalink
Add the "require-licence" rule
Browse files Browse the repository at this point in the history
WIP

WIP
  • Loading branch information
xenobytezero committed Jan 29, 2025
1 parent c955cb4 commit 3b6a152
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 0 deletions.
76 changes: 76 additions & 0 deletions docs/rules/require-license.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# require-license

💼 This rule is enabled in the ✅ `recommended` config.

<!-- end auto-generated rule header -->

This rule applies two validations to the `"licence"` property:

- It must be a string rather than any other data type
- It's value should match one of the values provided in the options

Example of **incorrect** code for this rule:

When the rule is configured with

```ts
{
"require-license": ["error", "GPL"]
}
```

```json
{
"license": "MIT"
}
```

When the rule is configured with

```ts
{
"require-license": ["error", ["MIT", "GPL"]]
}
```

```json
{
"license": "Apache"
}
```

Example of **correct** code for this rule:

When the rule is configured with

```ts
{
"require-license": ["error", "GPL"]
}
```

```json
{
"license": "GPL"
}
```

When the rule is configured with

```ts
{
"require-license": ["error", ["Apache", "MIT"]]
}
```

```json
{
"license": "Apache"
}
```

```json
{
"license": "MIT"
}
```
2 changes: 2 additions & 0 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { rule as noEmptyFields } from "./rules/no-empty-fields.js";
import { rule as noRedundantFiles } from "./rules/no-redundant-files.js";
import { rule as orderProperties } from "./rules/order-properties.js";
import { rule as preferRepositoryShorthand } from "./rules/repository-shorthand.js";
import { rule as requireLicense } from "./rules/require-license.js";
import { rule as sortCollections } from "./rules/sort-collections.js";
import { rule as uniqueDependencies } from "./rules/unique-dependencies.js";
import { rule as validLocalDependency } from "./rules/valid-local-dependency.js";
Expand All @@ -26,6 +27,7 @@ const rules: Record<string, PackageJsonRuleModule> = {
"no-redundant-files": noRedundantFiles,
"order-properties": orderProperties,
"repository-shorthand": preferRepositoryShorthand,
"require-license": requireLicense,
"sort-collections": sortCollections,
"unique-dependencies": uniqueDependencies,
"valid-local-dependency": validLocalDependency,
Expand Down
80 changes: 80 additions & 0 deletions src/rules/require-license.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { AST as JsonAST } from "jsonc-eslint-parser";

import * as ESTree from "estree";

import { createRule } from "../createRule.js";

export type AllowedValues = string | string[];
export type Options = [AllowedValues];

export function generateReportData(allowed: string[]) {
return {
allowed: allowed.map((v) => `'${v}'`).join(","),
multiple: allowed.length > 1 ? "one of" : "",
};
}

export const rule = createRule<Options>({
create(context) {
const ruleOptions = context.options[0];
const allowedValues = Array.isArray(ruleOptions)
? ruleOptions
: [ruleOptions];
return {
"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=license]"(
node: JsonAST.JSONProperty,
) {
if (
node.value.type !== "JSONLiteral" ||
typeof node.value.value !== "string"
) {
context.report({
messageId: "nonString",
node: node.value as unknown as ESTree.Node,
});
return;
}

if (!allowedValues.includes(node.value.value)) {
context.report({
data: generateReportData(allowedValues),
loc: node.loc,
messageId: "invalidValue",
});
}
},
};
},

meta: {
docs: {
category: "Best Practices",
description:
"Enforce the 'license' field to be a specific value/values",
recommended: false,
},
messages: {
invalidValue: '"license" must be{{multiple}} {{allowed}}"',
nonString: '"license" must be a string"',
},
schema: {
items: [
{
oneOf: [
{
items: {
type: "string",
},
type: "array",
},
{
type: "string",
},
],
},
],
type: "array",
},
type: "problem",
},
});
62 changes: 62 additions & 0 deletions src/tests/rules/require-license.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { generateReportData, rule } from "../../rules/require-license.js";
import { ruleTester } from "./ruleTester.js";

ruleTester.run("requires-license", rule, {
invalid: [
{
code: JSON.stringify({
license: "CC BY-SA",
name: "some-test-package",
}),
errors: [
{
data: generateReportData(["GPL"]),
messageId: "invalidValue",
},
],
options: ["GPL"],
},
{
code: JSON.stringify({
license: "Apache",
name: "some-test-package",
}),
errors: [
{
data: generateReportData(["MIT", "GPL"]),
messageId: "invalidValue",
},
],
options: [["MIT", "GPL"]],
},
{
code: JSON.stringify({
license: 1234,
name: "some-test-package",
}),
errors: [
{
data: generateReportData(["GPL"]),
messageId: "nonString",
},
],
options: ["GPL"],
},
],
valid: [
{
code: JSON.stringify({
license: "Apache",
name: "some-test-package",
}),
options: ["Apache"],
},
{
code: JSON.stringify({
license: "GPL",
name: "some-test-package",
}),
options: [["MIT", "GPL"]],
},
],
});

0 comments on commit 3b6a152

Please sign in to comment.