From 2473ae3b3798d4e70c8573b5a561e8b2c0134b56 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 27 Apr 2023 12:12:24 +0100 Subject: [PATCH] fix: print useful dep-check message (#1248) Format the dep-check error message to make it easier to read. --- .aegir.js | 21 +++++++++ package.json | 7 +-- src/dependency-check.js | 47 ++++++++++++++++--- test/dependency-check.js | 12 ++--- .../dependency-check/esm-pass/src/other.cjs | 4 +- .../dependency-check/fail-unused/index.js | 3 ++ .../dependency-check/fail-unused/package.json | 9 ++++ test/fixtures/dependency-check/pass/index.js | 2 + .../dependency-check/ts-pass/src/other.ts | 2 +- 9 files changed, 85 insertions(+), 22 deletions(-) create mode 100644 test/fixtures/dependency-check/fail-unused/index.js create mode 100644 test/fixtures/dependency-check/fail-unused/package.json diff --git a/.aegir.js b/.aegir.js index be220ea36..1a6e2c303 100644 --- a/.aegir.js +++ b/.aegir.js @@ -2,5 +2,26 @@ export default { docs: { entryPoint: 'utils' + }, + dependencyCheck: { + ignore: [ + '@typescript-eslint/eslint-plugin', + 'buffer', + 'c8', + 'conventional-changelog-conventionalcommits', + 'electron-mocha-main', + 'mocha', + 'npm-package-json-lint', + 'nyc', + 'path', + 'playwright-test', + 'react-native-test-runner', + 'semantic-release', + 'semantic-release-monorepo', + 'source-map-support', + 'typedoc-plugin-mdn-links', + 'typedoc-plugin-missing-exports', + 'electron' + ] } } diff --git a/package.json b/package.json index f036932f7..b5ef130c7 100644 --- a/package.json +++ b/package.json @@ -212,7 +212,7 @@ "lint": "node src/index.js lint", "test": "node src/index.js test", "docs": "node src/index.js docs", - "dep-check": "node src/index.js dep-check --unused false", + "dep-check": "node src/index.js dep-check", "doc-check": "node src/index.js doc-check", "test:node": "node src/index.js test -t node --cov", "test:chrome": "node src/index.js test -t browser --cov", @@ -237,7 +237,6 @@ "@types/chai-subset": "^1.3.3", "@types/mocha": "^10.0.0", "@types/node": "^18.11.15", - "@types/sinon": "^10.0.0", "@typescript-eslint/eslint-plugin": "^5.18.0", "buffer": "^6.0.3", "bytes": "^3.1.0", @@ -335,9 +334,7 @@ "@types/semver": "^7.3.4", "@types/update-notifier": "^6.0.1", "@types/yargs": "^17.0.0", - "electron": "^24.1.2", - "sinon": "^15.0.0", - "util": "^0.12.4" + "electron": "^24.1.2" }, "browser": { "fs": false, diff --git a/src/dependency-check.js b/src/dependency-check.js index 4d1d90c68..2a8ee4c26 100644 --- a/src/dependency-check.js +++ b/src/dependency-check.js @@ -1,5 +1,8 @@ +/* eslint-disable no-console */ + import { cwd } from 'process' import depcheck from 'depcheck' +import kleur from 'kleur' import Listr from 'listr' const ignoredDevDependencies = [ @@ -37,13 +40,43 @@ const tasks = new Listr( }, ignoreMatches: ignoredDevDependencies.concat(ctx.fileConfig.dependencyCheck.ignore).concat(ctx.ignore) }) - if (Object.keys(result.missing).length > 0 || (ctx.unused && (result.dependencies.length > 0 || result.devDependencies.length > 0))) { - throw new Error( - 'Some dependencies are missing or unused.\n' + - 'Missing: \n' + Object.entries(result.missing).map(([dep, path]) => dep + ': ' + path).join('\n') + - '\nUnused production dependencies: \n' + result.dependencies.join('\n') + '\n' + - 'Unused dev dependencies: \n' + result.devDependencies.join('\n') - ) + + if (Object.keys(result.missing).length > 0 || result.dependencies.length > 0 || result.devDependencies.length > 0) { + if (Object.keys(result.missing).length > 0) { + console.error('') + console.error('Missing dependencies:') + console.error('') + + Object.entries(result.missing).forEach(([dep, path]) => { + console.error(kleur.red(dep)) + console.error(' ', kleur.gray(path.join('\n '))) + }) + } + + if (result.dependencies.length > 0) { + console.error('') + console.error('Unused production dependencies:') + console.error('') + + result.dependencies.forEach(dep => { + console.error(kleur.yellow(dep)) + }) + } + + if (result.devDependencies.length > 0) { + console.error('') + console.error('Unused dev dependencies:') + console.error('') + + result.devDependencies.forEach(dep => { + console.error(kleur.yellow(dep)) + }) + } + + // necessary because otherwise listr removes the last line of output + console.error(' ') + + throw new Error('Some dependencies are missing or unused') } } } diff --git a/test/dependency-check.js b/test/dependency-check.js index 94f50d89b..0f8c2a7d5 100644 --- a/test/dependency-check.js +++ b/test/dependency-check.js @@ -43,7 +43,7 @@ describe('dependency check', () => { it('should pass when there are no missing deps', async () => { await expect( - execa(bin, ['dependency-check', '-u', 'false'], { + execa(bin, ['dependency-check'], { cwd: path.join(__dirname, 'fixtures/dependency-check/pass') }) ).to.eventually.be.fulfilled() @@ -51,7 +51,7 @@ describe('dependency check', () => { it('should pass when there are no missing deps in an esm project', async () => { await expect( - execa(bin, ['dependency-check', '-u', 'false'], { + execa(bin, ['dependency-check'], { cwd: path.join(__dirname, 'fixtures/dependency-check/esm-pass') }) ).to.eventually.be.fulfilled() @@ -59,7 +59,7 @@ describe('dependency check', () => { it('should pass when there are no missing deps in an ts project', async () => { await expect( - execa(bin, ['dependency-check', '-u', 'false'], { + execa(bin, ['dependency-check'], { cwd: path.join(__dirname, 'fixtures/dependency-check/ts-pass') }) ).to.eventually.be.fulfilled() @@ -68,11 +68,9 @@ describe('dependency check', () => { it('should check unused', async () => { await expect( execa(bin, ['dependency-check'], { - cwd: path.join(__dirname, 'fixtures/dependency-check/pass') + cwd: path.join(__dirname, 'fixtures/dependency-check/fail-unused') }) - ).to.eventually.be.rejected.with.property('message').that.include( - 'Unused production dependencies: \npico' - ) + ).to.eventually.be.rejectedWith('pico') }) /** diff --git a/test/fixtures/dependency-check/esm-pass/src/other.cjs b/test/fixtures/dependency-check/esm-pass/src/other.cjs index 77c6436d3..bf56d959f 100644 --- a/test/fixtures/dependency-check/esm-pass/src/other.cjs +++ b/test/fixtures/dependency-check/esm-pass/src/other.cjs @@ -1,3 +1,3 @@ -// @ts-nocheck /* eslint-disable no-unused-vars */ -import { execa } from 'execa' \ No newline at end of file +// @ts-ignore +const pico = require('pico') diff --git a/test/fixtures/dependency-check/fail-unused/index.js b/test/fixtures/dependency-check/fail-unused/index.js new file mode 100644 index 000000000..0499edc20 --- /dev/null +++ b/test/fixtures/dependency-check/fail-unused/index.js @@ -0,0 +1,3 @@ +/* eslint-disable no-unused-vars */ +// @ts-expect-error unused +import { execa } from 'execa' diff --git a/test/fixtures/dependency-check/fail-unused/package.json b/test/fixtures/dependency-check/fail-unused/package.json new file mode 100644 index 000000000..880bd29b7 --- /dev/null +++ b/test/fixtures/dependency-check/fail-unused/package.json @@ -0,0 +1,9 @@ +{ + "name": "dep-check-fail", + "version": "1.0.0", + "main": "index.js", + "dependencies": { + "execa": "1.0.0", + "pico": "1.0.0" + } +} diff --git a/test/fixtures/dependency-check/pass/index.js b/test/fixtures/dependency-check/pass/index.js index 076d0aa91..f59a0f0dd 100644 --- a/test/fixtures/dependency-check/pass/index.js +++ b/test/fixtures/dependency-check/pass/index.js @@ -3,3 +3,5 @@ // @ts-ignore import { execa } from 'execa' +// @ts-ignore +import pico from 'pico' diff --git a/test/fixtures/dependency-check/ts-pass/src/other.ts b/test/fixtures/dependency-check/ts-pass/src/other.ts index 0b6a46149..69b5dfea1 100644 --- a/test/fixtures/dependency-check/ts-pass/src/other.ts +++ b/test/fixtures/dependency-check/ts-pass/src/other.ts @@ -1,3 +1,3 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ // @ts-expect-error unused -import { execa } from 'execa' +import pico from 'pico'