diff --git a/src/rules/require-type.ts b/src/rules/require-type.ts new file mode 100644 index 00000000..9cf2ea65 --- /dev/null +++ b/src/rules/require-type.ts @@ -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; +}; diff --git a/src/rules/type-type.ts b/src/rules/type-type.ts new file mode 100755 index 00000000..407824e2 --- /dev/null +++ b/src/rules/type-type.ts @@ -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; +}; diff --git a/src/rules/valid-values-type.ts b/src/rules/valid-values-type.ts new file mode 100755 index 00000000..5ecba8fa --- /dev/null +++ b/src/rules/valid-values-type.ts @@ -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(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; +}; diff --git a/test/unit/rules/require-type.test.ts b/test/unit/rules/require-type.test.ts new file mode 100755 index 00000000..4da10c46 --- /dev/null +++ b/test/unit/rules/require-type.test.ts @@ -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'); + }); + }); +}); diff --git a/test/unit/rules/type-type.test.ts b/test/unit/rules/type-type.test.ts new file mode 100755 index 00000000..5ad047be --- /dev/null +++ b/test/unit/rules/type-type.test.ts @@ -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(); + }); + }); +}); diff --git a/test/unit/rules/valid-values-type.test.ts b/test/unit/rules/valid-values-type.test.ts new file mode 100755 index 00000000..1d383276 --- /dev/null +++ b/test/unit/rules/valid-values-type.test.ts @@ -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(); + }); + }); +}); diff --git a/website/docs/rules.md b/website/docs/rules.md index a8a71274..78fd1d9f 100644 --- a/website/docs/rules.md +++ b/website/docs/rules.md @@ -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) @@ -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) @@ -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 diff --git a/website/docs/rules/required-node/require-type.md b/website/docs/rules/required-node/require-type.md new file mode 100644 index 00000000..a28398c8 --- /dev/null +++ b/website/docs/rules/required-node/require-type.md @@ -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 diff --git a/website/docs/rules/type/type-type.md b/website/docs/rules/type/type-type.md new file mode 100644 index 00000000..b4460538 --- /dev/null +++ b/website/docs/rules/type/type-type.md @@ -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 diff --git a/website/docs/rules/valid-values/valid-values-type.md b/website/docs/rules/valid-values/valid-values-type.md new file mode 100644 index 00000000..3a470dec --- /dev/null +++ b/website/docs/rules/valid-values/valid-values-type.md @@ -0,0 +1,85 @@ +--- +id: valid-values-type +title: valid-values-type +--- + +Enabling this rule will result in an error being generated if the value in `type` is not equal to one of the values in the array of valid values. + +## Example .npmpackagejsonlintrc configuration + +```json +{ + "rules": { + "valid-values-type": ["error", [ + "module" + ]] + } +} +``` + +## Rule Details + +### *Incorrect* example(s) + +```json +{ + "type": "commonjs" +} +``` + +### *Correct* example(s) + +```json +{ + "type": "module" +} +``` + +## Example .npmpackagejsonlintrc configuration + +```json +{ + "type": [ + "commonjs", + "module" + ] +} +``` + +## Rule Details + +### *Incorrect* example(s) + +```json +{ + "type": "type" +} +``` + +### *Correct* example(s) + +```json +{ + "type": "commonjs" +} +``` + +```json +{ + "type": "module" +} +``` + +## Shorthand for disabling the rule in .npmpackagejsonlintrc configuration + +```json +{ + "rules": { + "valid-values-type": "off" + } +} +``` + +## History + +* Introduced in version 7.0.1