Skip to content

Commit

Permalink
feat: New rules for type field (#1087)
Browse files Browse the repository at this point in the history
* Added type field rules and tests

* Added documentation for type field rules

* Correct lint errors

---------

Co-authored-by: Thomas Lindner <5178550+tclindner@users.noreply.github.com>
  • Loading branch information
tom-fletcher and tclindner committed Nov 5, 2023
1 parent f9a64b2 commit d73d1ca
Show file tree
Hide file tree
Showing 10 changed files with 394 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/rules/require-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {PackageJson} from 'type-fest';
import {LintIssue} from '../lint-issue';
import {RuleType} from '../types/rule-type';
import {Severity} from '../types/severity';

const lintId = 'require-type';
const nodeName = 'type';
const message = 'type is required';

export const ruleType = RuleType.Standard;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const lint = (packageJsonData: PackageJson | any, severity: Severity): LintIssue | null => {
if (!packageJsonData.hasOwnProperty(nodeName)) {
return new LintIssue(lintId, severity, nodeName, message);
}

return null;
};
20 changes: 20 additions & 0 deletions src/rules/type-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {PackageJson} from 'type-fest';
import {LintIssue} from '../lint-issue';
import {isString} from '../validators/type';
import {RuleType} from '../types/rule-type';
import {Severity} from '../types/severity';

const lintId = 'type-type';
const nodeName = 'type';
const message = 'Type should be a string';

export const ruleType = RuleType.Standard;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const lint = (packageJsonData: PackageJson | any, severity: Severity): LintIssue | null => {
if (!isString(packageJsonData, nodeName)) {
return new LintIssue(lintId, severity, nodeName, message);
}

return null;
};
40 changes: 40 additions & 0 deletions src/rules/valid-values-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {PackageJson} from 'type-fest';
import {LintIssue} from '../lint-issue';
import {LintResult} from '../types/lint-result';
import {RuleType} from '../types/rule-type';
import {Severity} from '../types/severity';
import {isValidValue} from '../validators/valid-values';

const lintId = 'valid-values-type';
const nodeName = 'type';

export const ruleType = RuleType.Array;

export const minItems = 1;

/**
* [function description]
* @param {Object} packageJsonData Valid package.json object
* @param {String} severity 'error' or 'warning'
* @param {Array} validValues An array of valid values
* @return {Object|Boolean} LintIssue object if invalid. True if valid
*/
export const lint = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
packageJsonData: PackageJson | any,
severity: Severity,
validValues: string[]
): LintResult => {
if (!isValidValue<string>(packageJsonData, nodeName, packageJsonData[nodeName], validValues)) {
return new LintIssue(
lintId,
severity,
nodeName,
`Invalid value for type. Current value is ${packageJsonData[nodeName]}. Valid values include: ${validValues.join(
', '
)}.`
);
}

return null;
};
33 changes: 33 additions & 0 deletions test/unit/rules/require-type.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {lint, ruleType} from '../../../src/rules/require-type';
import {Severity} from '../../../src/types/severity';

describe('require-type Unit Tests', () => {
describe('a rule type value should be exported', () => {
test('it should equal "standard"', () => {
expect(ruleType).toStrictEqual('standard');
});
});

describe('when package.json has node', () => {
test('true should be returned', () => {
const packageJsonData = {
type: 'module',
};
const response = lint(packageJsonData, Severity.Error);

expect(response).toBeNull();
});
});

describe('when package.json does not have node', () => {
test('LintIssue object should be returned', () => {
const packageJsonData = {};
const response = lint(packageJsonData, Severity.Error);

expect(response.lintId).toStrictEqual('require-type');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('type');
expect(response.lintMessage).toStrictEqual('type is required');
});
});
});
44 changes: 44 additions & 0 deletions test/unit/rules/type-type.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {lint, ruleType} from '../../../src/rules/type-type';
import {Severity} from '../../../src/types/severity';

describe('type-type Unit Tests', () => {
describe('a rule type value should be exported', () => {
test('it should equal "standard"', () => {
expect(ruleType).toStrictEqual('standard');
});
});

describe('when package.json has node with correct type', () => {
test('true should be returned', () => {
const packageJsonData = {
type: 'module',
};
const response = lint(packageJsonData, Severity.Error);

expect(response).toBeNull();
});
});

describe('when package.json has node with incorrect type', () => {
test('LintIssue object should be returned', () => {
const packageJsonData = {
type: true,
};
const response = lint(packageJsonData, Severity.Error);

expect(response.lintId).toStrictEqual('type-type');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('type');
expect(response.lintMessage).toStrictEqual('Type should be a string');
});
});

describe('when package.json does not have node', () => {
test('true should be returned', () => {
const packageJsonData = {};
const response = lint(packageJsonData, Severity.Error);

expect(response).toBeNull();
});
});
});
54 changes: 54 additions & 0 deletions test/unit/rules/valid-values-type.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {lint, ruleType, minItems} from '../../../src/rules/valid-values-type';
import {Severity} from '../../../src/types/severity';

describe('valid-values-type Unit Tests', () => {
describe('a rule type value should be exported', () => {
test('it should equal "array"', () => {
expect(ruleType).toStrictEqual('array');
});
});

describe('a minItems value should be exported', () => {
test('it should equal 1', () => {
expect(minItems).toStrictEqual(1);
});
});

describe('when package.json has node with incorrect format', () => {
test('LintIssue object should be returned', () => {
const packageJsonData = {
type: 'type',
};
const validValues = ['commonjs', 'module'];
const response = lint(packageJsonData, Severity.Error, validValues);

expect(response.lintId).toStrictEqual('valid-values-type');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('type');
expect(response.lintMessage).toStrictEqual(
'Invalid value for type. Current value is type. Valid values include: commonjs, module.'
);
});
});

describe('when package.json has node with correct format', () => {
test('LintIssue object should be returned', () => {
const packageJsonData = {
type: 'module',
};
const validValues = ['commonjs', 'module'];
const response = lint(packageJsonData, Severity.Error, validValues);

expect(response).toBeNull();
});
});

describe('when package.json does not have node', () => {
test('true should be returned', () => {
const packageJsonData = {};
const response = lint(packageJsonData, Severity.Error, []);

expect(response).toBeNull();
});
});
});
3 changes: 3 additions & 0 deletions website/docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Rules allow npm-package-json-lint to be fully customizable. npm-package-json-lin
* [require-repository-directory](rules/required-node/require-repository-directory.md)
* [require-repository](rules/required-node/require-repository.md)
* [require-scripts](rules/required-node/require-scripts.md)
* [require-type](rules/required-node/require-type.md)
* [require-types](rules/required-node/require-types.md)
* [require-typings](rules/required-node/require-typings.md)
* [require-version](rules/required-node/require-version.md)
Expand Down Expand Up @@ -70,6 +71,7 @@ Rules allow npm-package-json-lint to be fully customizable. npm-package-json-lin
* [private-type](rules/type/private-type.md)
* [repository-type](rules/type/repository-type.md)
* [scripts-type](rules/type/scripts-type.md)
* [type-type](rules/type/type-type.md)
* [version-type](rules/type/version-type.md)


Expand All @@ -83,6 +85,7 @@ Rules allow npm-package-json-lint to be fully customizable. npm-package-json-lin
* [valid-values-name-scope](rules/valid-values/valid-values-name-scope.md)
* [valid-values-private](rules/valid-values/valid-values-private.md)
* [valid-values-publishConfig](rules/valid-values/valid-values-publishConfig.md)
* [valid-values-type](rules/valid-values/valid-values-type.md)

## Dependency rules

Expand Down
38 changes: 38 additions & 0 deletions website/docs/rules/required-node/require-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
id: require-type
title: require-type
---

Enabling this rule will result in an error being generated if `type` is missing from the package.json file.

## Example .npmpackagejsonlintrc configuration

```json
{
"rules": {
"require-type": "error"
}
}
```

## Rule Details

### *Incorrect* example(s)

```json
{

}
```

### *Correct* example(s)

```json
{
"type": "module"
}
```

## History

* Introduced in version 7.0.1
58 changes: 58 additions & 0 deletions website/docs/rules/type/type-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
id: type-type
title: type-type
---

Enabling this rule will result in an error being generated if the value in `type` is not a string.

## Example .npmpackagejsonlintrc configuration

```json
{
"rules": {
"type-type": "error"
}
}
```

## Rule Details

### *Incorrect* example(s)

```json
{
"type": 1
}
```

```json
{
"type": ["true"]
}
```

```json
{
"type": true
}
```

```json
{
"type": {
"enabled": "true"
}
}
```

### *Correct* example(s)

```json
{
"type": "module"
}
```

## History

* Introduced in version 7.0.1

0 comments on commit d73d1ca

Please sign in to comment.