From b66a3a8dac165bfd27bf44a4af06ca2e53821d89 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Tue, 22 Aug 2023 14:00:22 -0400 Subject: [PATCH] fix(linter): error on dependencies that are only in devDependencies instead of production dependencies --- .../src/rules/dependency-checks.spec.ts | 60 +++++++++++++++++-- .../src/rules/dependency-checks.ts | 16 +++-- .../src/utils/package-json-utils.ts | 10 ++++ 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/packages/eslint-plugin/src/rules/dependency-checks.spec.ts b/packages/eslint-plugin/src/rules/dependency-checks.spec.ts index f1966332ed10b..9f4c136715812 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.spec.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.spec.ts @@ -446,7 +446,7 @@ describe('Dependency checks (eslint)', () => { ); expect(failures.length).toEqual(1); expect(failures[0].message).toMatchInlineSnapshot(` - "The "liba" project uses the following packages, but they are missing from the "dependencies": + "The "liba" project uses the following packages, but they are missing from "dependencies": - external2" `); expect(failures[0].line).toEqual(3); @@ -1462,11 +1462,63 @@ describe('Dependency checks (eslint)', () => { ); expect(failures.length).toEqual(1); expect(failures[0].message).toMatchInlineSnapshot(` - "The "liba" project uses the following packages, but they are missing from the "dependencies": + "The "liba" project uses the following packages, but they are missing from "dependencies": - tslib" `); expect(failures[0].line).toEqual(3); }); + + it('should report missing package if it is in devDependencies', () => { + const packageJson = { + name: '@mycompany/liba', + dependencies: {}, + devDependencies: { + external1: '^16.0.0', + }, + }; + + const fileSys = { + './libs/liba/package.json': JSON.stringify(packageJson, null, 2), + './libs/liba/src/index.ts': '', + './package.json': JSON.stringify(rootPackageJson, null, 2), + }; + vol.fromJSON(fileSys, '/root'); + + const failures = runRule( + {}, + `/root/libs/liba/package.json`, + JSON.stringify(packageJson, null, 2), + { + nodes: { + liba: { + name: 'liba', + type: 'lib', + data: { + root: 'libs/liba', + targets: { + build: {}, + }, + }, + }, + }, + externalNodes, + dependencies: { + liba: [{ source: 'liba', target: 'npm:external1', type: 'static' }], + }, + }, + { + liba: [ + createFile(`libs/liba/src/main.ts`, ['npm:external1']), + createFile(`libs/liba/package.json`), + ], + } + ); + expect(failures.length).toEqual(1); + expect(failures[0].message).toMatchInlineSnapshot(` + "The "liba" project uses the following packages, but they are missing from "dependencies": + - external1" + `); + }); }); it('should require swc if @nx/js:swc executor', () => { @@ -1525,8 +1577,8 @@ it('should require swc if @nx/js:swc executor', () => { ); expect(failures.length).toEqual(1); expect(failures[0].message).toMatchInlineSnapshot(` - "The "liba" project uses the following packages, but they are missing from the "dependencies": - - @swc/helpers" + "The "liba" project uses the following packages, but they are missing from "dependencies": + - @swc/helpers" `); expect(failures[0].line).toEqual(3); }); diff --git a/packages/eslint-plugin/src/rules/dependency-checks.ts b/packages/eslint-plugin/src/rules/dependency-checks.ts index 8b2c7d59d0af0..4c122b9d9ff64 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.ts @@ -11,6 +11,7 @@ import { findProject, getSourceFilePath } from '../utils/runtime-lint-utils'; import { getAllDependencies, getPackageJson, + getProductionDependencies, } from '../utils/package-json-utils'; export type Options = [ @@ -57,7 +58,7 @@ export default createESLintRule({ }, ], messages: { - missingDependency: `The "{{projectName}}" project uses the following packages, but they are missing from the "{{section}}":{{packageNames}}`, + missingDependency: `The "{{projectName}}" project uses the following packages, but they are missing from "{{section}}":{{packageNames}}`, obsoleteDependency: `The "{{packageName}}" package is not used by "{{projectName}}" project.`, versionMismatch: `The version specifier does not contain the installed version of "{{packageName}}" package: {{version}}.`, missingDependencySection: `Dependency sections are missing from the "package.json" but following dependencies were detected:{{dependencies}}`, @@ -142,7 +143,7 @@ export default createESLintRule({ 'package.json' ); - globalThis.projPackageJsonDeps ??= getAllDependencies( + globalThis.projPackageJsonDeps ??= getProductionDependencies( getPackageJson(projPackageJsonPath) ); const projPackageJsonDeps: Record = @@ -283,12 +284,9 @@ export default createESLintRule({ if ( !node.properties || !node.properties.some((p) => - [ - 'dependencies', - 'peerDependencies', - 'devDependencies', - 'optionalDependencies', - ].includes((p.key as any).value) + ['dependencies', 'peerDependencies', 'optionalDependencies'].includes( + (p.key as any).value + ) ) ) { context.report({ @@ -326,7 +324,7 @@ export default createESLintRule({ } return { - ['JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=/^(dev|peer|optional)?dependencies$/i]']( + ['JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=/^(peer|optional)?dependencies$/i]']( node: AST.JSONProperty ) { validateMissingDependencies(node); diff --git a/packages/eslint-plugin/src/utils/package-json-utils.ts b/packages/eslint-plugin/src/utils/package-json-utils.ts index 178e9d09e83c0..33230ea15fff3 100644 --- a/packages/eslint-plugin/src/utils/package-json-utils.ts +++ b/packages/eslint-plugin/src/utils/package-json-utils.ts @@ -13,6 +13,16 @@ export function getAllDependencies( }; } +export function getProductionDependencies( + packageJson: PackageJson +): Record { + return { + ...packageJson.dependencies, + ...packageJson.peerDependencies, + ...packageJson.optionalDependencies, + }; +} + export function getPackageJson(path: string): PackageJson { if (existsSync(path)) { return readJsonFile(path);