From 2176e7428fa29608b685ce89384ff45bc88ac8be Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Thu, 17 Nov 2022 03:22:25 +0200 Subject: [PATCH] refactor: make a subcommand --- .changeset/nice-cycles-search.md | 3 +- .../plugin-commands-licenses/src/licenses.ts | 80 +++---------------- .../src/licensesList.ts | 70 ++++++++++++++++ .../plugin-commands-licenses/test/index.ts | 8 +- 4 files changed, 89 insertions(+), 72 deletions(-) create mode 100644 packages/plugin-commands-licenses/src/licensesList.ts diff --git a/.changeset/nice-cycles-search.md b/.changeset/nice-cycles-search.md index e559953ff32..ffc77ae688f 100644 --- a/.changeset/nice-cycles-search.md +++ b/.changeset/nice-cycles-search.md @@ -1,6 +1,7 @@ --- '@pnpm/license-scanner': major '@pnpm/plugin-commands-licenses': major +"pnpm": minor --- -Added new command named licenses which displays the licenses of the packages +Added a new command `pnpm licenses list`, which displays the licenses of the packages [#2825](https://github.com/pnpm/pnpm/issues/2825) diff --git a/packages/plugin-commands-licenses/src/licenses.ts b/packages/plugin-commands-licenses/src/licenses.ts index b1070987b99..7bfee3d12d2 100644 --- a/packages/plugin-commands-licenses/src/licenses.ts +++ b/packages/plugin-commands-licenses/src/licenses.ts @@ -1,23 +1,18 @@ import { docsUrl, readDepNameCompletions, - readProjectManifestOnly, } from '@pnpm/cli-utils' -import { getStorePath } from '@pnpm/store-path' import { CompletionFunc } from '@pnpm/command' -import { WANTED_LOCKFILE } from '@pnpm/constants' -import { readWantedLockfile } from '@pnpm/lockfile-file' import { FILTERING, OPTIONS, UNIVERSAL_OPTIONS, } from '@pnpm/common-cli-options-help' -import { Config, types as allTypes } from '@pnpm/config' +import { types as allTypes } from '@pnpm/config' import { PnpmError } from '@pnpm/error' -import { findDependencyLicenses } from '@pnpm/license-scanner' import pick from 'ramda/src/pick' import renderHelp from 'render-help' -import { renderLicences } from './outputRenderer' +import { licensesList, LicensesCommandOptions } from './licensesList' export function rcOptionsTypes () { return { @@ -47,9 +42,8 @@ export function help () { description: `Check for licenses packages. The check can be limited to a subset of the installed packages by providing arguments (patterns are supported). Examples: -pnpm licenses -pnpm licenses --long -pnpm licenses gulp-* @babel/core`, +pnpm licenses list +pnpm licenses list --long`, descriptionLists: [ { title: 'Options', @@ -94,67 +88,19 @@ export const completion: CompletionFunc = async (cliOpts) => { return readDepNameCompletions(cliOpts.dir as string) } -export type LicensesCommandOptions = { - compatible?: boolean - long?: boolean - recursive?: boolean - json?: boolean -} & Pick< -Config, -| 'dev' -| 'dir' -| 'lockfileDir' -| 'registries' -| 'optional' -| 'production' -| 'storeDir' -| 'virtualStoreDir' -| 'modulesDir' -| 'pnpmHomeDir' -> & -Partial> - export async function handler ( opts: LicensesCommandOptions, params: string[] = [] ) { - const lockfile = await readWantedLockfile(opts.lockfileDir ?? opts.dir, { - ignoreIncompatible: true, - }) - if (lockfile == null) { - throw new PnpmError( - 'LICENSES_NO_LOCKFILE', - `No ${WANTED_LOCKFILE} found: Cannot check a project without a lockfile` - ) + if (params.length === 0) { + throw new PnpmError('LICENCES_NO_SUBCOMMAND', 'Please specify the subcommand') + } + switch (params[0]) { + case 'list': + case 'ls': + return licensesList(opts) + default: { + throw new PnpmError('LICENSES_UNKNOWN_SUBCOMMAND', 'This subcommand is not known') } - - const include = { - dependencies: opts.production !== false, - devDependencies: opts.dev !== false, - optionalDependencies: opts.optional !== false, } - - const manifest = await readProjectManifestOnly(opts.dir, {}) - - const storeDir = await getStorePath({ - pkgRoot: opts.dir, - storePath: opts.storeDir, - pnpmHomeDir: opts.pnpmHomeDir, - }) - - const licensePackages = await findDependencyLicenses({ - include, - lockfileDir: opts.dir, - storeDir, - virtualStoreDir: opts.virtualStoreDir ?? '.', - modulesDir: opts.modulesDir, - registries: opts.registries, - wantedLockfile: lockfile, - manifest, - }) - - if (licensePackages.length === 0) - return { output: 'No licenses in packages found', exitCode: 0 } - - return renderLicences(licensePackages, opts) } diff --git a/packages/plugin-commands-licenses/src/licensesList.ts b/packages/plugin-commands-licenses/src/licensesList.ts new file mode 100644 index 00000000000..d1f01596cda --- /dev/null +++ b/packages/plugin-commands-licenses/src/licensesList.ts @@ -0,0 +1,70 @@ +import { readProjectManifestOnly } from '@pnpm/cli-utils' +import { Config } from '@pnpm/config' +import { PnpmError } from '@pnpm/error' +import { getStorePath } from '@pnpm/store-path' +import { WANTED_LOCKFILE } from '@pnpm/constants' +import { readWantedLockfile } from '@pnpm/lockfile-file' +import { findDependencyLicenses } from '@pnpm/license-scanner' +import { renderLicences } from './outputRenderer' + +export type LicensesCommandOptions = { + compatible?: boolean + long?: boolean + recursive?: boolean + json?: boolean +} & Pick< +Config, +| 'dev' +| 'dir' +| 'lockfileDir' +| 'registries' +| 'optional' +| 'production' +| 'storeDir' +| 'virtualStoreDir' +| 'modulesDir' +| 'pnpmHomeDir' +> & +Partial> + +export async function licensesList (opts: LicensesCommandOptions) { + const lockfile = await readWantedLockfile(opts.lockfileDir ?? opts.dir, { + ignoreIncompatible: true, + }) + if (lockfile == null) { + throw new PnpmError( + 'LICENSES_NO_LOCKFILE', + `No ${WANTED_LOCKFILE} found: Cannot check a project without a lockfile` + ) + } + + const include = { + dependencies: opts.production !== false, + devDependencies: opts.dev !== false, + optionalDependencies: opts.optional !== false, + } + + const manifest = await readProjectManifestOnly(opts.dir, {}) + + const storeDir = await getStorePath({ + pkgRoot: opts.dir, + storePath: opts.storeDir, + pnpmHomeDir: opts.pnpmHomeDir, + }) + + const licensePackages = await findDependencyLicenses({ + include, + lockfileDir: opts.dir, + storeDir, + virtualStoreDir: opts.virtualStoreDir ?? '.', + modulesDir: opts.modulesDir, + registries: opts.registries, + wantedLockfile: lockfile, + manifest, + }) + + if (licensePackages.length === 0) + return { output: 'No licenses in packages found', exitCode: 0 } + + return renderLicences(licensePackages, opts) +} diff --git a/packages/plugin-commands-licenses/test/index.ts b/packages/plugin-commands-licenses/test/index.ts index 922ce455e61..ad382686ca0 100644 --- a/packages/plugin-commands-licenses/test/index.ts +++ b/packages/plugin-commands-licenses/test/index.ts @@ -47,7 +47,7 @@ test('pnpm licenses', async () => { // we need to prefix it with v3 otherwise licenses tool can't find anything // in the content-addressable directory storeDir: path.resolve(storeDir, 'v3'), - }) + }, ['list']) expect(exitCode).toBe(0) expect(stripAnsi(output)).toMatchSnapshot('show-packages') @@ -74,7 +74,7 @@ test('pnpm licenses: show details', async () => { // we need to prefix it with v3 otherwise licenses tool can't find anything // in the content-addressable directory storeDir: path.resolve(storeDir, 'v3'), - }) + }, ['list']) expect(exitCode).toBe(0) expect(stripAnsi(output)).toMatchSnapshot('show-packages-details') @@ -102,7 +102,7 @@ test('pnpm licenses: output as json', async () => { // we need to prefix it with v3 otherwise licenses tool can't find anything // in the content-addressable directory storeDir: path.resolve(storeDir, 'v3'), - }) + }, ['list']) expect(exitCode).toBe(0) expect(output).not.toHaveLength(0) @@ -129,7 +129,7 @@ test('pnpm licenses: fails when lockfile is missing', async () => { dir: path.resolve('./test/fixtures/invalid'), pnpmHomeDir: '', long: true, - }) + }, ['list']) ).rejects.toThrowErrorMatchingInlineSnapshot( '"No pnpm-lock.yaml found: Cannot check a project without a lockfile"' )