feat: pnpm ls --depth -1 prints projects

close #1519
PR #1521
This commit is contained in:
Zoltan Kochan
2018-11-28 03:22:06 +02:00
committed by Zoltan Kochan
parent f8e80397c9
commit 8a88e43911
9 changed files with 78 additions and 46 deletions

View File

@@ -80,12 +80,14 @@ export default async function (
) {
const opts = { ...DEFAULTS, ...maybeOpts }
const tree = await dh(projectPath, {
depth: opts.depth,
only: opts.only,
registries: opts.registries,
shrinkwrapDirectory: maybeOpts && maybeOpts.shrinkwrapDirectory,
})
const tree = opts.depth === -1
? []
: await dh(projectPath, {
depth: opts.depth,
only: opts.only,
registries: opts.registries,
shrinkwrapDirectory: maybeOpts && maybeOpts.shrinkwrapDirectory,
})
const print = getPrinter(opts.parseable)
const entryPkg = await readPkg(path.resolve(projectPath, 'package.json'))

View File

@@ -1,7 +1,5 @@
import { PackageNode } from 'dependencies-hierarchy'
import path = require('path')
import R = require('ramda')
import readPkg from './readPkg'
const sortPackages = R.sortBy(R.prop('name'))
@@ -30,13 +28,11 @@ export default async function (
return [
firstLine,
...pkgs.map((pkg) => `${pkg.path}:${pkg.name}@${pkg.version}`),
'',
].join('\n')
}
return [
project.path,
...pkgs.map((pkg) => pkg.path),
'',
].join('\n')
}

View File

@@ -38,7 +38,7 @@ export default async function (
}),
})
return s
return s.replace(/\n$/, '')
}
async function toArchyTree (

View File

@@ -19,7 +19,7 @@ test('list all deps of a package that has an external shrinkwrap.yaml', async (t
}), stripIndent`
pkg@1.0.0 ${fixtureWithExternalShrinkwrap}
└── is-positive@1.0.0
` + '\n')
`)
t.end()
})
@@ -30,7 +30,7 @@ test('list with default parameters', async t => {
├── is-negative@2.1.0
├── is-positive@3.1.0
└── write-json-file@2.2.0
` + '\n')
`)
t.end()
})
@@ -41,7 +41,7 @@ test('list with default parameters in pkg that has no name and version', async t
├── is-negative@2.1.0
├── is-positive@3.1.0
└── write-json-file@2.2.0
` + '\n')
`)
t.end()
})
@@ -52,7 +52,7 @@ test('list with default parameters in pkg that has no version', async t => {
├── is-negative@2.1.0
├── is-positive@3.1.0
└── write-json-file@2.2.0
` + '\n')
`)
t.end()
})
@@ -61,7 +61,7 @@ test('list dev only', async t => {
t.equal(await list(fixture, { only: 'dev' }), stripIndent`
fixture@1.0.0 ${fixture}
└── is-positive@3.1.0
` + '\n')
`)
t.end()
})
@@ -70,7 +70,7 @@ test('list prod only', async t => {
t.equal(await list(fixture, { only: 'prod' }), stripIndent`
fixture@1.0.0 ${fixture}
└── write-json-file@2.2.0
` + '\n')
`)
t.end()
})
@@ -90,7 +90,7 @@ test('list prod only with depth 2', async t => {
├── graceful-fs@4.1.11
├── imurmurhash@0.1.4
└── slide@1.1.6
` + '\n')
`)
t.end()
})
@@ -107,7 +107,13 @@ test('list with depth 1', async t => {
├── pify@2.3.0
├── sort-keys@1.1.2
└── write-file-atomic@2.1.0
` + '\n')
`)
t.end()
})
test('list with depth -1', async t => {
t.equal(await list(fixture, { depth: -1 }), `fixture@1.0.0 ${fixture}`)
t.end()
})
@@ -119,7 +125,7 @@ test('list with depth 1 and selected packages', async t => {
└─┬ write-json-file@2.2.0
├── ${highlighted('make-dir@1.0.0')}
└── ${highlighted('pify@2.3.0')}
` + '\n')
`)
t.end()
})
@@ -139,7 +145,7 @@ test('list in long format', async t => {
Stringify and write JSON to a file atomically
git+https://github.com/sindresorhus/write-json-file.git
https://github.com/sindresorhus/write-json-file#readme
` + '\n')
`)
t.end()
})
@@ -156,7 +162,7 @@ test('parseable list with depth 1', async t => {
${path.join(fixture, 'node_modules/.registry.npmjs.org/sort-keys/1.1.2')}
${path.join(fixture, 'node_modules/.registry.npmjs.org/write-file-atomic/2.1.0')}
${path.join(fixture, 'node_modules/.registry.npmjs.org/write-json-file/2.2.0')}
` + '\n')
`)
t.end()
})
@@ -165,7 +171,7 @@ test('parseable list with depth 1 and dev only', async t => {
t.equal(await list(fixture, { parseable: true, depth: 1, only: 'dev' }), stripIndent`
${fixture}
${path.join(fixture, 'node_modules/.registry.npmjs.org/is-positive/3.1.0')}
` + '\n')
`)
t.end()
})
@@ -182,7 +188,7 @@ test('long parseable list with depth 1', async t => {
${path.join(fixture, 'node_modules/.registry.npmjs.org/sort-keys/1.1.2')}:sort-keys@1.1.2
${path.join(fixture, 'node_modules/.registry.npmjs.org/write-file-atomic/2.1.0')}:write-file-atomic@2.1.0
${path.join(fixture, 'node_modules/.registry.npmjs.org/write-json-file/2.2.0')}:write-json-file@2.2.0
` + '\n')
`)
t.end()
})
@@ -199,7 +205,7 @@ test('long parseable list with depth 1 when package has no version', async t =>
${path.join(fixtureWithNoPkgVersion, 'node_modules/.registry.npmjs.org/sort-keys/1.1.2')}:sort-keys@1.1.2
${path.join(fixtureWithNoPkgVersion, 'node_modules/.registry.npmjs.org/write-file-atomic/2.1.0')}:write-file-atomic@2.1.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.registry.npmjs.org/write-json-file/2.2.0')}:write-json-file@2.2.0
` + '\n')
`)
t.end()
})
@@ -216,13 +222,13 @@ test('long parseable list with depth 1 when package has no name and no version',
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.registry.npmjs.org/sort-keys/1.1.2')}:sort-keys@1.1.2
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.registry.npmjs.org/write-file-atomic/2.1.0')}:write-file-atomic@2.1.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.registry.npmjs.org/write-json-file/2.2.0')}:write-json-file@2.2.0
` + '\n')
`)
t.end()
})
test('print empty', async t => {
t.equal(await list(emptyFixture), `empty@1.0.0 ${emptyFixture}\n`)
t.equal(await list(emptyFixture), `empty@1.0.0 ${emptyFixture}`)
t.end()
})
@@ -255,6 +261,6 @@ test('unsaved dependencies are marked', async (t) => {
), stripIndent`
fixture@1.0.0 ${fixture}
└── foo@1.0.0 ${chalk.whiteBright.bgBlack('not saved')}
` + '\n')
`)
t.end()
})

View File

@@ -171,6 +171,9 @@ function getHelpText (command: string) {
--parseable show parseable output instead of tree view
-g, --global list packages in the global install prefix instead of in the current project
--depth max display depth of the dependency tree
--depth 0 display only direct dependencies
--depth -1 display only projects. Useful in a monorepo.
\`pnpm recursive ls --depth -1\` lists all projects in a monorepo.
--prod, --production display only the dependency tree for packages in \`dependencies\`.
--dev display only the dependency tree for packages in \`devDependencies\`.
`

View File

@@ -13,6 +13,25 @@ export default async function (
shrinkwrapDirectory?: string,
},
command: string,
) {
const output = await render(args, opts, command)
if (output) console.log(output)
}
export async function render (
args: string[],
opts: {
alwaysPrintRootPackage?: boolean,
depth?: number,
development: boolean,
long?: boolean,
parseable?: boolean,
prefix: string,
production: boolean,
shrinkwrapDirectory?: string,
},
command: string,
) {
opts.long = opts.long || command === 'll' || command === 'la'
const only = (opts.production && opts.development ? undefined : (opts.production ? 'prod' : 'dev')) as ('prod' | 'dev' | undefined) // tslint:disable-line:no-unnecessary-type-assertion
@@ -24,9 +43,7 @@ export default async function (
parseable: opts.parseable,
shrinkwrapDirectory: opts.shrinkwrapDirectory,
}
const output = args.length
? await listForPackages(args, opts.prefix, listOpts)
: await list(opts.prefix, listOpts)
if (output) console.log(output)
return args.length
? listForPackages(args, opts.prefix, listOpts)
: list(opts.prefix, listOpts)
}

View File

@@ -1,6 +1,6 @@
import logger from '@pnpm/logger'
import { PackageJson } from '@pnpm/types'
import list from '../list'
import { render as renderList } from '../list'
export default async (
pkgs: Array<{path: string, manifest: PackageJson}>,
@@ -15,13 +15,21 @@ export default async (
shrinkwrapDirectory?: string,
},
) => {
const outputs = []
for (const pkg of pkgs) {
try {
await list(args, { ...opts, prefix: pkg.path, alwaysPrintRootPackage: false }, cmd)
const output = await renderList(args, { ...opts, prefix: pkg.path, alwaysPrintRootPackage: opts.depth === -1 }, cmd)
if (!output) continue
outputs.push(output)
} catch (err) {
logger.info(err)
err['prefix'] = pkg.path // tslint:disable-line:no-string-literal
throw err
}
}
if (outputs.length === 0) return
const joiner = opts.depth && opts.depth > -1 ? '\n\n' : '\n'
const allOutput = outputs.join(joiner)
console.log(allOutput)
}

View File

@@ -34,7 +34,7 @@ test('listing global packages', async (t: tape.Test) => {
t.equal(result.stdout.toString(), stripIndent`
${globalPrefix}
└── is-positive@3.1.0
` + '\n\n')
` + '\n')
})
test('listing global packages installed with independent-leaves = true', async (t: tape.Test) => {
@@ -57,7 +57,7 @@ test('listing global packages installed with independent-leaves = true', async (
t.equal(result.stdout.toString(), stripIndent`
${globalPrefix}
└── is-positive@3.1.0
` + '\n\n')
` + '\n')
})
test('listing packages', async (t: tape.Test) => {
@@ -80,7 +80,7 @@ test('listing packages', async (t: tape.Test) => {
t.equal(result.stdout.toString(), stripIndent`
project@0.0.0 ${process.cwd()}
└── is-positive@1.0.0
` + '\n\n', 'prints prod deps only')
` + '\n', 'prints prod deps only')
}
{
@@ -91,7 +91,7 @@ test('listing packages', async (t: tape.Test) => {
t.equal(result.stdout.toString(), stripIndent`
project@0.0.0 ${process.cwd()}
└── is-positive@1.0.0
` + '\n\n', 'prints prod deps only using --only prod')
` + '\n', 'prints prod deps only using --only prod')
}
{
@@ -102,7 +102,7 @@ test('listing packages', async (t: tape.Test) => {
t.equal(result.stdout.toString(), stripIndent`
project@0.0.0 ${process.cwd()}
└── is-negative@1.0.0
` + '\n\n', 'prints dev deps only')
` + '\n', 'prints dev deps only')
}
{
@@ -113,7 +113,7 @@ test('listing packages', async (t: tape.Test) => {
t.equal(result.stdout.toString(), stripIndent`
project@0.0.0 ${process.cwd()}
└── is-negative@1.0.0
` + '\n\n', 'prints dev deps only using --only dev')
` + '\n', 'prints dev deps only using --only dev')
}
{
@@ -125,7 +125,7 @@ test('listing packages', async (t: tape.Test) => {
project@0.0.0 ${process.cwd()}
├── is-negative@1.0.0
└── is-positive@1.0.0
` + '\n\n', 'prints all deps')
` + '\n', 'prints all deps')
}
})
@@ -155,5 +155,5 @@ test('listing packages of a project that has an external shrinkwrap.yaml', async
t.equal(result.stdout.toString(), stripIndent`
pkg@1.0.0 ${process.cwd()}
└── is-positive@1.0.0
` + '\n\n', 'prints all deps')
` + '\n', 'prints all deps')
})

View File

@@ -49,7 +49,7 @@ test('recursive list', async (t: tape.Test) => {
project-2@1.0.0 ${path.resolve('project-2')}
└── is-negative@1.0.0
` + '\n\n')
` + '\n')
})
test('recursive list with shared-workspace-shrinkwrap', async (t: tape.Test) => {
@@ -92,7 +92,7 @@ test('recursive list with shared-workspace-shrinkwrap', async (t: tape.Test) =>
project-2@1.0.0 ${path.resolve('project-2')}
└── is-negative@1.0.0
` + '\n\n')
` + '\n')
})
test('recursive list --scope', async (t: tape.Test) => {
@@ -138,5 +138,5 @@ test('recursive list --scope', async (t: tape.Test) => {
project-2@1.0.0 ${path.resolve('project-2')}
└── is-negative@1.0.0
` + '\n\n')
` + '\n')
})