Skip to content

Commit

Permalink
Improve output for no-restricted-* rules (#615)
Browse files Browse the repository at this point in the history
  • Loading branch information
tclindner committed Mar 20, 2022
1 parent 81aa1d0 commit 947bcc2
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 64 deletions.
16 changes: 12 additions & 4 deletions src/rules/no-restricted-dependencies.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {PackageJson} from 'type-fest';
import {hasDependency} from '../validators/dependency-audit';
import {auditDependenciesWithRestrictedVersion} from '../validators/dependency-audit';
import {LintIssue} from '../lint-issue';
import {RuleType} from '../types/rule-type';
import {Severity} from '../types/severity';

const lintId = 'no-restricted-dependencies';
const nodeName = 'dependencies';
const message = 'You are using a restricted dependency. Please remove it.';

export const ruleType = RuleType.Array;

Expand All @@ -18,8 +17,17 @@ export const lint = (
severity: Severity,
invalidDependencies: string[]
): LintIssue | null => {
if (hasDependency(packageJsonData, nodeName, invalidDependencies)) {
return new LintIssue(lintId, severity, nodeName, message);
const auditResult = auditDependenciesWithRestrictedVersion(packageJsonData, nodeName, invalidDependencies);

if (auditResult.hasDependencyWithRestrictedVersion) {
return new LintIssue(
lintId,
severity,
nodeName,
`You are using a restricted dependency. Please remove it. Invalid ${nodeName} include: ${auditResult.dependenciesWithRestrictedVersion.join(
', '
)}`
);
}

return null;
Expand Down
16 changes: 12 additions & 4 deletions src/rules/no-restricted-devDependencies.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {PackageJson} from 'type-fest';
import {hasDependency} from '../validators/dependency-audit';
import {auditDependenciesWithRestrictedVersion} from '../validators/dependency-audit';
import {LintIssue} from '../lint-issue';
import {RuleType} from '../types/rule-type';
import {Severity} from '../types/severity';

const lintId = 'no-restricted-devDependencies';
const nodeName = 'devDependencies';
const message = 'You are using a restricted dependency. Please remove it.';

export const ruleType = RuleType.Array;

Expand All @@ -18,8 +17,17 @@ export const lint = (
severity: Severity,
invalidDependencies: string[]
): LintIssue | null => {
if (hasDependency(packageJsonData, nodeName, invalidDependencies)) {
return new LintIssue(lintId, severity, nodeName, message);
const auditResult = auditDependenciesWithRestrictedVersion(packageJsonData, nodeName, invalidDependencies);

if (auditResult.hasDependencyWithRestrictedVersion) {
return new LintIssue(
lintId,
severity,
nodeName,
`You are using a restricted dependency. Please remove it. Invalid ${nodeName} include: ${auditResult.dependenciesWithRestrictedVersion.join(
', '
)}`
);
}

return null;
Expand Down
16 changes: 12 additions & 4 deletions src/rules/no-restricted-pre-release-dependencies.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {PackageJson} from 'type-fest';
import {hasDepPrereleaseVers} from '../validators/dependency-audit';
import {auditDependenciesWithRestrictedPrereleaseVersion} from '../validators/dependency-audit';
import {LintIssue} from '../lint-issue';
import {RuleType} from '../types/rule-type';
import {Severity} from '../types/severity';

const lintId = 'no-restricted-pre-release-dependencies';
const nodeName = 'dependencies';
const message = 'You are using a restricted pre-release dependency. Please remove it.';

export const ruleType = RuleType.Array;

Expand All @@ -18,8 +17,17 @@ export const lint = (
severity: Severity,
invalidPreRelDeps: string[]
): LintIssue | null => {
if (hasDepPrereleaseVers(packageJsonData, nodeName, invalidPreRelDeps)) {
return new LintIssue(lintId, severity, nodeName, message);
const auditResult = auditDependenciesWithRestrictedPrereleaseVersion(packageJsonData, nodeName, invalidPreRelDeps);

if (auditResult.hasDependencyWithRestrictedPrereleaseVersion) {
return new LintIssue(
lintId,
severity,
nodeName,
`You are using a restricted pre-release dependency. Please remove it. Invalid ${nodeName} include: ${auditResult.dependenciesWithRestrictedPrereleaseVersion.join(
', '
)}`
);
}

return null;
Expand Down
16 changes: 12 additions & 4 deletions src/rules/no-restricted-pre-release-devDependencies.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {PackageJson} from 'type-fest';
import {hasDepPrereleaseVers} from '../validators/dependency-audit';
import {auditDependenciesWithRestrictedPrereleaseVersion} from '../validators/dependency-audit';
import {LintIssue} from '../lint-issue';
import {RuleType} from '../types/rule-type';
import {Severity} from '../types/severity';

const lintId = 'no-restricted-pre-release-devDependencies';
const nodeName = 'devDependencies';
const message = 'You are using a restricted pre-release dependency. Please remove it.';

export const ruleType = RuleType.Array;

Expand All @@ -18,8 +17,17 @@ export const lint = (
severity: Severity,
invalidPreRelDeps: string[]
): LintIssue | null => {
if (hasDepPrereleaseVers(packageJsonData, nodeName, invalidPreRelDeps)) {
return new LintIssue(lintId, severity, nodeName, message);
const auditResult = auditDependenciesWithRestrictedPrereleaseVersion(packageJsonData, nodeName, invalidPreRelDeps);

if (auditResult.hasDependencyWithRestrictedPrereleaseVersion) {
return new LintIssue(
lintId,
severity,
nodeName,
`You are using a restricted pre-release dependency. Please remove it. Invalid ${nodeName} include: ${auditResult.dependenciesWithRestrictedPrereleaseVersion.join(
', '
)}`
);
}

return null;
Expand Down
89 changes: 67 additions & 22 deletions src/validators/dependency-audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,92 @@ const semver = require('semver');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const hasExceptions = (config: any): boolean => typeof config === 'object' && config.hasOwnProperty('exceptions');

export interface AuditDependenciesWithRestrictedVersionResponse {
hasDependencyWithRestrictedVersion: boolean;
dependenciesWithRestrictedVersion: string[];
dependenciesWithoutRestrictedVersion: string[];
}

/**
* Determines whether or not the package has a given dependency
* @param {object} packageJsonData Valid JSON
* @param {string} nodeName Name of a node in the package.json file
* @param {string} depsToCheckFor An array of packages to check for
* @return {boolean} True if the package has a dependency. False if it is not or the node is missing.
* @param packageJsonData Valid JSON
* @param nodeName Name of a node in the package.json file
* @param depsToCheckFor An array of packages to check for
* @return True if the package has a dependency. False if it is not or the node is missing.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const hasDependency = (packageJsonData: PackageJson | any, nodeName: string, depsToCheckFor: string[]): boolean => {
export const auditDependenciesWithRestrictedVersion = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
packageJsonData: PackageJson | any,
nodeName: string,
depsToCheckFor: string[]
): AuditDependenciesWithRestrictedVersionResponse => {
let hasDependencyWithRestrictedVersion = false;
const dependenciesWithRestrictedVersion = [];
const dependenciesWithoutRestrictedVersion = [];

if (!packageJsonData.hasOwnProperty(nodeName)) {
return false;
return {
hasDependencyWithRestrictedVersion,
dependenciesWithRestrictedVersion,
dependenciesWithoutRestrictedVersion,
};
}

// eslint-disable-next-line no-restricted-syntax, guard-for-in
for (const dependencyName in packageJsonData[nodeName]) {
// eslint-disable-next-line no-restricted-syntax
for (const depToCheckFor of depsToCheckFor) {
if (depToCheckFor === dependencyName) {
return true;
}

if (
hasDependencyWithRestrictedVersion = true;
dependenciesWithRestrictedVersion.push(dependencyName);
} else if (
depToCheckFor.endsWith('*') &&
dependencyName.startsWith(depToCheckFor.slice(0, Math.max(0, depToCheckFor.length - 1)))
) {
return true;
hasDependencyWithRestrictedVersion = true;
dependenciesWithRestrictedVersion.push(dependencyName);
} else {
dependenciesWithoutRestrictedVersion.push(dependencyName);
}
}
}

return false;
return {
hasDependencyWithRestrictedVersion,
dependenciesWithRestrictedVersion,
dependenciesWithoutRestrictedVersion,
};
};

export interface AuditDependenciesWithRestrictedPrereleaseVersionResponse {
hasDependencyWithRestrictedPrereleaseVersion: boolean;
dependenciesWithRestrictedPrereleaseVersion: string[];
dependenciesWithoutRestrictedPrereleaseVersion: string[];
}

/**
* Determines whether or not the package has a pre-release version of a given dependency
* @param {object} packageJsonData Valid JSON
* @param {string} nodeName Name of a node in the package.json file
* @param {string} depsToCheckFor An array of packages to check for
* @return {boolean} True if the package has a pre-release version of a dependency. False if it is not or the node is missing.
* @param packageJsonData Valid JSON
* @param nodeName Name of a node in the package.json file
* @param depsToCheckFor An array of packages to check for
* @return True if the package has a pre-release version of a dependency. False if it is not or the node is missing.
*/
export const hasDepPrereleaseVers = (
export const auditDependenciesWithRestrictedPrereleaseVersion = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
packageJsonData: PackageJson | any,
nodeName: string,
depsToCheckFor: string[]
): boolean => {
): AuditDependenciesWithRestrictedPrereleaseVersionResponse => {
let hasDependencyWithRestrictedPrereleaseVersion = false;
const dependenciesWithRestrictedPrereleaseVersion = [];
const dependenciesWithoutRestrictedPrereleaseVersion = [];

if (!packageJsonData.hasOwnProperty(nodeName)) {
return false;
return {
hasDependencyWithRestrictedPrereleaseVersion,
dependenciesWithRestrictedPrereleaseVersion,
dependenciesWithoutRestrictedPrereleaseVersion,
};
}

// eslint-disable-next-line no-restricted-syntax
Expand All @@ -63,12 +101,19 @@ export const hasDepPrereleaseVers = (
const dependencyVersion = packageJsonData[nodeName][dependencyName];

if (dependencyVersion.includes('-beta') || dependencyVersion.includes('-rc')) {
return true;
hasDependencyWithRestrictedPrereleaseVersion = true;
dependenciesWithRestrictedPrereleaseVersion.push(dependencyName);
} else {
dependenciesWithoutRestrictedPrereleaseVersion.push(dependencyName);
}
}
}

return false;
return {
hasDependencyWithRestrictedPrereleaseVersion,
dependenciesWithRestrictedPrereleaseVersion,
dependenciesWithoutRestrictedPrereleaseVersion,
};
};

export interface AuditDependenciesWithMajorVersionOfZeroResponse {
Expand Down
8 changes: 6 additions & 2 deletions test/unit/rules/no-restricted-dependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ describe('no-restricted-dependencies Unit Tests', () => {
expect(response.lintId).toStrictEqual('no-restricted-dependencies');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('dependencies');
expect(response.lintMessage).toStrictEqual('You are using a restricted dependency. Please remove it.');
expect(response.lintMessage).toStrictEqual(
'You are using a restricted dependency. Please remove it. Invalid dependencies include: npm-package-json-lint'
);
});
});

Expand All @@ -44,7 +46,9 @@ describe('no-restricted-dependencies Unit Tests', () => {
expect(response.lintId).toStrictEqual('no-restricted-dependencies');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('dependencies');
expect(response.lintMessage).toStrictEqual('You are using a restricted dependency. Please remove it.');
expect(response.lintMessage).toStrictEqual(
'You are using a restricted dependency. Please remove it. Invalid dependencies include: @types/node'
);
});
});

Expand Down
8 changes: 6 additions & 2 deletions test/unit/rules/no-restricted-devDependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ describe('no-restricted-devDependencies Unit Tests', () => {
expect(response.lintId).toStrictEqual('no-restricted-devDependencies');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('devDependencies');
expect(response.lintMessage).toStrictEqual('You are using a restricted dependency. Please remove it.');
expect(response.lintMessage).toStrictEqual(
'You are using a restricted dependency. Please remove it. Invalid devDependencies include: npm-package-json-lint'
);
});
});

Expand All @@ -44,7 +46,9 @@ describe('no-restricted-devDependencies Unit Tests', () => {
expect(response.lintId).toStrictEqual('no-restricted-devDependencies');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('devDependencies');
expect(response.lintMessage).toStrictEqual('You are using a restricted dependency. Please remove it.');
expect(response.lintMessage).toStrictEqual(
'You are using a restricted dependency. Please remove it. Invalid devDependencies include: @types/node'
);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ describe('no-restricted-pre-release-dependencies Unit Tests', () => {
expect(response.lintId).toStrictEqual('no-restricted-pre-release-dependencies');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('dependencies');
expect(response.lintMessage).toStrictEqual('You are using a restricted pre-release dependency. Please remove it.');
expect(response.lintMessage).toStrictEqual(
'You are using a restricted pre-release dependency. Please remove it. Invalid dependencies include: npm-package-json-lint'
);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ describe('no-restricted-pre-release-devDependencies Unit Tests', () => {
expect(response.lintId).toStrictEqual('no-restricted-pre-release-devDependencies');
expect(response.severity).toStrictEqual('error');
expect(response.node).toStrictEqual('devDependencies');
expect(response.lintMessage).toStrictEqual('You are using a restricted pre-release dependency. Please remove it.');
expect(response.lintMessage).toStrictEqual(
'You are using a restricted pre-release dependency. Please remove it. Invalid devDependencies include: npm-package-json-lint'
);
});
});

Expand Down

0 comments on commit 947bcc2

Please sign in to comment.