fix: path info in dependencies hierarchy tree (#6001)

* fix: get correct path info in dependencies hierarchy tree

* chore: test case for build dependencies hierarchy

* docs: update changeset

* chore: test cases

* fix: show full path in dependencies hierarchy tree
This commit is contained in:
await-ovo
2023-02-02 09:34:16 +08:00
committed by GitHub
parent 9ac6940442
commit 19e823beab
18 changed files with 205 additions and 72 deletions

View File

@@ -0,0 +1,7 @@
---
"@pnpm/plugin-commands-listing": patch
"@pnpm/reviewing.dependencies-hierarchy": patch
"@pnpm/list": patch
---
Show correct path info for dependenciesHierarchy tree

3
.gitignore vendored
View File

@@ -44,3 +44,6 @@ RELEASE.md
.jest-cache
.verdaccio-cache
.turbo
## custom modules-dir fixture
__fixtures__/custom-modules-dir/**/fake_modules/

View File

@@ -0,0 +1,2 @@
modules-dir=fake_modules
virtual-store-dir=fake_modules/.fake_store

View File

@@ -0,0 +1,5 @@
{
"name": "custom-modules-dir",
"private": true,
"version": "1.0.0"
}

View File

@@ -0,0 +1,7 @@
{
"name": "@scope/bar",
"version": "1.0.0",
"dependencies": {
"is-positive": "1.0.0"
}
}

View File

@@ -0,0 +1,8 @@
{
"name": "@scope/foo",
"version": "1.0.0",
"dependencies": {
"@scope/bar": "workspace:*",
"is-positive": "3.1.0"
}
}

View File

@@ -0,0 +1,32 @@
lockfileVersion: 5.4
importers:
.:
specifiers: {}
packages/bar:
specifiers:
is-positive: 1.0.0
dependencies:
is-positive: 1.0.0
packages/foo:
specifiers:
'@scope/bar': workspace:*
is-positive: 3.1.0
dependencies:
'@scope/bar': link:../bar
is-positive: 3.1.0
packages:
/is-positive/1.0.0:
resolution: {integrity: sha512-xxzPGZ4P2uN6rROUa5N9Z7zTX6ERuE0hs6GUOc/cKBLF2NqKc16UwqHMt3tFg4CO6EBTE5UecUasg+3jZx3Ckg==}
engines: {node: '>=0.10.0'}
dev: false
/is-positive/3.1.0:
resolution: {integrity: sha512-8ND1j3y9/HP94TOvGzr69/FgbkX2ruOldhLEsTWwcJVfo4oRjwemJmJxt7RJkKYH8tz7vYBP9JcKQY8CLuJ90Q==}
engines: {node: '>=0.10.0'}
dev: false

View File

@@ -0,0 +1,2 @@
packages:
- 'packages/*'

View File

@@ -2,4 +2,5 @@ scripts:
prepareFixtures: >
node ../pnpm/dist/pnpm.cjs install -rf --frozen-lockfile --no-shared-workspace-lockfile --no-link-workspace-packages &&
node ../pnpm/dist/pnpm.cjs install -rf -C fixtureWithLinks --frozen-lockfile --link-workspace-packages --no-shared-workspace-lockfile &&
cd ./fixture-with-external-shrinkwrap/pkg && node ../../../pnpm/dist/pnpm.cjs install -f --frozen-lockfile
cd ./fixture-with-external-shrinkwrap/pkg && node ../../../pnpm/dist/pnpm.cjs install -f --frozen-lockfile &&
cd ../../custom-modules-dir && node ../../pnpm/dist/pnpm.cjs install -f --frozen-lockfile

View File

@@ -37,12 +37,13 @@ export async function buildDependenciesHierarchy (
onlyProjects?: boolean
search?: SearchFunction
lockfileDir: string
modulesDir?: string
}
): Promise<{ [projectDir: string]: DependenciesHierarchy }> {
if (!maybeOpts?.lockfileDir) {
throw new TypeError('opts.lockfileDir is required')
}
const modulesDir = await realpathMissing(path.join(maybeOpts.lockfileDir, 'node_modules'))
const modulesDir = await realpathMissing(path.join(maybeOpts.lockfileDir, maybeOpts.modulesDir ?? 'node_modules'))
const modules = await readModulesManifest(modulesDir)
const registries = normalizeRegistries({
...maybeOpts?.registries,
@@ -71,6 +72,8 @@ export async function buildDependenciesHierarchy (
registries,
search: maybeOpts.search,
skipped: new Set(modules?.skipped ?? []),
modulesDir: maybeOpts.modulesDir,
virtualStoreDir: modules?.virtualStoreDir,
}
; (
await Promise.all(projectPaths.map(async (projectPath) => {
@@ -96,13 +99,15 @@ async function dependenciesHierarchyForPackage (
search?: SearchFunction
skipped: Set<string>
lockfileDir: string
modulesDir?: string
virtualStoreDir?: string
}
) {
const importerId = getLockfileImporterId(opts.lockfileDir, projectPath)
if (!currentLockfile.importers[importerId]) return {}
const modulesDir = path.join(projectPath, 'node_modules')
const modulesDir = path.join(projectPath, opts.modulesDir ?? 'node_modules')
const savedDeps = getAllDirectDependencies(currentLockfile.importers[importerId])
const allDirectDeps = await readModulesDir(modulesDir) ?? []
@@ -122,6 +127,7 @@ async function dependenciesHierarchyForPackage (
search: opts.search,
skipped: opts.skipped,
wantedPackages: wantedLockfile.packages ?? {},
virtualStoreDir: opts.virtualStoreDir,
})
const parentId: TreeNodeId = { type: 'importer', importerId }
const result: DependenciesHierarchy = {}
@@ -134,11 +140,11 @@ async function dependenciesHierarchyForPackage (
currentPackages: currentLockfile.packages ?? {},
rewriteLinkVersionDir: projectPath,
linkedPathBaseDir: projectPath,
modulesDir,
ref,
registries: opts.registries,
skipped: opts.skipped,
wantedPackages: wantedLockfile.packages ?? {},
virtualStoreDir: opts.virtualStoreDir,
})
let newEntry: PackageNode | null = null
const matchedSearched = opts.search?.(packageInfo)

View File

@@ -14,13 +14,13 @@ import normalizePath from 'normalize-path'
export interface GetPkgInfoOpts {
readonly alias: string
readonly modulesDir: string
readonly ref: string
readonly currentPackages: PackageSnapshots
readonly peers?: Set<string>
readonly registries: Registries
readonly skipped: Set<string>
readonly wantedPackages: PackageSnapshots
readonly virtualStoreDir?: string
/**
* The base dir if the `ref` argument is a `"link:"` relative path.
@@ -74,7 +74,7 @@ export function getPkgInfo (opts: GetPkgInfoOpts): PackageInfo {
version = opts.ref
}
const fullPackagePath = depPath
? path.join(opts.modulesDir, '.pnpm', depPathToFilename(depPath))
? path.join(opts.virtualStoreDir ?? '.pnpm', depPathToFilename(depPath), 'node_modules', name)
: path.join(opts.linkedPathBaseDir, opts.ref.slice(5))
if (version.startsWith('link:') && opts.rewriteLinkVersionDir) {

View File

@@ -11,7 +11,6 @@ import { serializeTreeNodeId, TreeNodeId } from './TreeNodeId'
interface GetTreeOpts {
maxDepth: number
rewriteLinkVersionDir: string
modulesDir: string
includeOptionalDependencies: boolean
lockfileDir: string
onlyProjects?: boolean
@@ -21,6 +20,7 @@ interface GetTreeOpts {
importers: Record<string, ProjectSnapshot>
currentPackages: PackageSnapshots
wantedPackages: PackageSnapshots
virtualStoreDir?: string
}
interface DependencyInfo {
@@ -127,12 +127,12 @@ function getTreeHelper (
currentPackages: opts.currentPackages,
rewriteLinkVersionDir: opts.rewriteLinkVersionDir,
linkedPathBaseDir,
modulesDir: opts.modulesDir,
peers,
ref,
registries: opts.registries,
skipped: opts.skipped,
wantedPackages: opts.wantedPackages,
virtualStoreDir: opts.virtualStoreDir,
})
let circular: boolean
const matchedSearched = opts.search?.(packageInfo)

View File

@@ -85,7 +85,7 @@ describe('getTree', () => {
const getTreeArgs = {
maxDepth: 0,
rewriteLinkVersionDir: '',
modulesDir: '',
virtualStoreDir: '.pnpm',
importers: {},
includeOptionalDependencies: false,
lockfileDir: '',

View File

@@ -15,6 +15,7 @@ const withUnsavedDepsFixture = f.find('with-unsaved-deps')
const fixtureMonorepo = path.join(__dirname, '..', 'fixtureMonorepo')
const withAliasedDepFixture = f.find('with-aliased-dep')
const workspaceWithNestedWorkspaceDeps = f.find('workspace-with-nested-workspace-deps')
const customModulesDirFixture = f.find('custom-modules-dir')
test('one package depth 0', async () => {
const tree = await buildDependenciesHierarchy([generalFixture], { depth: 0, lockfileDir: generalFixture })
@@ -30,7 +31,7 @@ test('one package depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'minimatch',
path: path.join(modulesDir, '.pnpm/minimatch@3.0.4'),
path: path.join(modulesDir, '.pnpm/minimatch@3.0.4/node_modules/minimatch'),
resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz',
version: '3.0.4',
},
@@ -41,7 +42,7 @@ test('one package depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'rimraf',
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1'),
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1/node_modules/rimraf'),
resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz',
version: '2.5.1',
},
@@ -54,7 +55,7 @@ test('one package depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'is-positive',
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0'),
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0/node_modules/is-positive'),
resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz',
version: '1.0.0',
},
@@ -68,7 +69,7 @@ test('one package depth 0', async () => {
isSkipped: false,
name: 'is-negative',
optional: true,
path: path.join(modulesDir, '.pnpm/is-negative@1.0.0'),
path: path.join(modulesDir, '.pnpm/is-negative@1.0.0/node_modules/is-negative'),
resolved: 'https://registry.npmjs.org/is-negative/-/is-negative-1.0.0.tgz',
version: '1.0.0',
},
@@ -91,7 +92,7 @@ test('one package depth 1', async () => {
isPeer: false,
isSkipped: false,
name: 'minimatch',
path: path.join(modulesDir, '.pnpm/minimatch@3.0.4'),
path: path.join(modulesDir, '.pnpm/minimatch@3.0.4/node_modules/minimatch'),
resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz',
version: '3.0.4',
@@ -103,7 +104,7 @@ test('one package depth 1', async () => {
isPeer: false,
isSkipped: false,
name: 'brace-expansion',
path: path.join(modulesDir, '.pnpm/brace-expansion@1.1.8'),
path: path.join(modulesDir, '.pnpm/brace-expansion@1.1.8/node_modules/brace-expansion'),
resolved: 'https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz',
version: '1.1.8',
},
@@ -116,7 +117,7 @@ test('one package depth 1', async () => {
isPeer: false,
isSkipped: false,
name: 'rimraf',
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1'),
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1/node_modules/rimraf'),
resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz',
version: '2.5.1',
@@ -128,7 +129,7 @@ test('one package depth 1', async () => {
isPeer: false,
isSkipped: false,
name: 'glob',
path: path.join(modulesDir, '.pnpm/glob@6.0.4'),
path: path.join(modulesDir, '.pnpm/glob@6.0.4/node_modules/glob'),
resolved: 'https://registry.npmjs.org/glob/-/glob-6.0.4.tgz',
version: '6.0.4',
},
@@ -143,7 +144,7 @@ test('one package depth 1', async () => {
isPeer: false,
isSkipped: false,
name: 'is-positive',
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0'),
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0/node_modules/is-positive'),
resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz',
version: '1.0.0',
},
@@ -157,7 +158,7 @@ test('one package depth 1', async () => {
isSkipped: false,
name: 'is-negative',
optional: true,
path: path.join(modulesDir, '.pnpm/is-negative@1.0.0'),
path: path.join(modulesDir, '.pnpm/is-negative@1.0.0/node_modules/is-negative'),
resolved: 'https://registry.npmjs.org/is-negative/-/is-negative-1.0.0.tgz',
version: '1.0.0',
},
@@ -191,7 +192,7 @@ test('only prod depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'minimatch',
path: path.join(modulesDir, '.pnpm/minimatch@3.0.4'),
path: path.join(modulesDir, '.pnpm/minimatch@3.0.4/node_modules/minimatch'),
resolved: 'https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz',
version: '3.0.4',
},
@@ -202,7 +203,7 @@ test('only prod depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'rimraf',
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1'),
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1/node_modules/rimraf'),
resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz',
version: '2.5.1',
},
@@ -236,7 +237,7 @@ test('only dev depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'is-positive',
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0'),
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0/node_modules/is-positive'),
resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz',
version: '1.0.0',
},
@@ -282,7 +283,7 @@ test('filter 1 package with depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'rimraf',
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1'),
path: path.join(modulesDir, '.pnpm/rimraf@2.5.1/node_modules/rimraf'),
resolved: 'https://registry.npmjs.org/rimraf/-/rimraf-2.5.1.tgz',
searched: true,
version: '2.5.1',
@@ -310,7 +311,7 @@ test('circular dependency', async () => {
})
function resolvePaths (modulesDir: string, node: PackageNode): PackageNode {
const p = path.resolve(modulesDir, '.pnpm', node.path)
const p = path.resolve(modulesDir, '.pnpm', node.path, 'node_modules', node.name)
if (node.dependencies == null) {
return {
...node,
@@ -349,7 +350,7 @@ test('local package depth 0', async () => {
isPeer: false,
isSkipped: false,
name: 'is-positive',
path: path.join(modulesDir, '.pnpm/is-positive@3.1.0'),
path: path.join(modulesDir, '.pnpm/is-positive@3.1.0/node_modules/is-positive'),
resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-3.1.0.tgz',
version: '3.1.0',
},
@@ -435,7 +436,7 @@ test('unsaved dependencies are listed', async () => {
isPeer: false,
isSkipped: false,
name: 'symlink-dir',
path: path.join(modulesDir, '.pnpm/symlink-dir@2.0.2'),
path: path.join(modulesDir, '.pnpm/symlink-dir@2.0.2/node_modules/symlink-dir'),
resolved: 'https://registry.npmjs.org/symlink-dir/-/symlink-dir-2.0.2.tgz',
version: '2.0.2',
},
@@ -478,7 +479,7 @@ test('unsaved dependencies are listed and filtered', async () => {
isPeer: false,
isSkipped: false,
name: 'symlink-dir',
path: path.join(modulesDir, '.pnpm/symlink-dir@2.0.2'),
path: path.join(modulesDir, '.pnpm/symlink-dir@2.0.2/node_modules/symlink-dir'),
resolved: 'https://registry.npmjs.org/symlink-dir/-/symlink-dir-2.0.2.tgz',
searched: true,
version: '2.0.2',
@@ -509,7 +510,7 @@ test('dependency with an alias', async () => {
isPeer: false,
isSkipped: false,
name: 'is-positive',
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0'),
path: path.join(modulesDir, '.pnpm/is-positive@1.0.0/node_modules/is-positive'),
resolved: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz',
version: '1.0.0',
},
@@ -542,7 +543,7 @@ test('dependency without a package.json', async () => {
isPeer: false,
isSkipped: false,
name: `camelcase#${commit}`,
path: path.join(withNonPackageDepFixture, 'node_modules', '.pnpm', `github.com+${org}+${pkg}@${commit}`),
path: path.join(withNonPackageDepFixture, 'node_modules', '.pnpm', `github.com+${org}+${pkg}@${commit}`, 'node_modules', `camelcase#${commit}`),
resolved: `https://codeload.github.com/${org}/${pkg}/tar.gz/${commit}`,
version: '0.0.0',
},
@@ -561,3 +562,54 @@ test('dependency without a package.json', async () => {
expect(tree[withNonPackageDepFixture].dependencies![0]).not.toHaveProperty(['devDependencies'])
expect(tree[withNonPackageDepFixture].dependencies![0]).not.toHaveProperty(['optionalDependencies'])
})
test('on custom modules-dir workspaces', async () => {
const tree = await buildDependenciesHierarchy(
[customModulesDirFixture, path.join(customModulesDirFixture, './packages/foo'), path.join(customModulesDirFixture, './packages/bar')],
{ depth: 1000, lockfileDir: customModulesDirFixture, modulesDir: 'fake_modules' }
)
expect(tree).toEqual({
[customModulesDirFixture]: {
dependencies: [],
devDependencies: [],
optionalDependencies: [],
},
[path.join(customModulesDirFixture, 'packages/foo')]: {
dependencies: [
expect.objectContaining({
alias: '@scope/bar',
version: 'link:../bar',
path: path.join(customModulesDirFixture, 'packages/bar'),
dependencies: [
expect.objectContaining({
alias: 'is-positive',
name: 'is-positive',
path: path.join(customModulesDirFixture, 'fake_modules/.fake_store/is-positive@1.0.0/node_modules/is-positive'),
version: '1.0.0',
}),
],
}),
expect.objectContaining({
alias: 'is-positive',
name: 'is-positive',
path: path.join(customModulesDirFixture, 'fake_modules/.fake_store/is-positive@3.1.0/node_modules/is-positive'),
version: '3.1.0',
}),
],
devDependencies: [],
optionalDependencies: [],
},
[path.join(customModulesDirFixture, 'packages/bar')]: {
dependencies: [
expect.objectContaining({
alias: 'is-positive',
name: 'is-positive',
path: path.join(customModulesDirFixture, 'fake_modules/.fake_store/is-positive@1.0.0/node_modules/is-positive'),
version: '1.0.0',
}),
],
devDependencies: [],
optionalDependencies: [],
},
})
})

View File

@@ -18,7 +18,7 @@ export type PkgInfo = Omit<PkgData, 'name' | 'path'> & Pick<ProjectManifest, 'de
export async function getPkgInfo (pkg: PkgData): Promise<PkgInfo> {
let manifest
try {
manifest = await readPkg(path.join(pkg.path, 'node_modules', pkg.name, 'package.json'))
manifest = await readPkg(path.join(pkg.path, 'package.json'))
} catch (err: any) { // eslint-disable-line
// This will probably never happen
manifest = {

View File

@@ -27,6 +27,7 @@ export async function searchForPackages (
include?: { [dependenciesField in DependenciesField]: boolean }
onlyProjects?: boolean
registries?: Registries
modulesDir?: string
}
) {
const search = createPackagesSearcher(packages)
@@ -39,6 +40,7 @@ export async function searchForPackages (
onlyProjects: opts.onlyProjects,
registries: opts.registries,
search,
modulesDir: opts.modulesDir,
}))
.map(async ([projectPath, buildDependenciesHierarchy]) => {
const entryPkg = await readProjectManifestOnly(projectPath)
@@ -65,6 +67,7 @@ export async function listForPackages (
onlyProjects?: boolean
reportAs?: 'parseable' | 'tree' | 'json'
registries?: Registries
modulesDir?: string
}
) {
const opts = { ...DEFAULTS, ...maybeOpts }
@@ -93,6 +96,7 @@ export async function list (
reportAs?: 'parseable' | 'tree' | 'json'
registries?: Registries
showExtraneous?: boolean
modulesDir?: string
}
) {
const opts = { ...DEFAULTS, ...maybeOpts }
@@ -110,6 +114,7 @@ export async function list (
lockfileDir: maybeOpts?.lockfileDir,
onlyProjects: maybeOpts?.onlyProjects,
registries: opts.registries,
modulesDir: opts.modulesDir,
})
)
.map(async ([projectPath, dependenciesHierarchy]) => {

View File

@@ -257,9 +257,9 @@ test('parseable list in workspace with private package', async () => {
reportAs: 'parseable',
lockfileDir: workspaceWithPrivatePkgs,
})).toBe(`${path.join(workspaceWithPrivatePkgs, 'packages/private')}
${path.join(workspaceWithPrivatePkgs, 'packages/private/node_modules/.pnpm/is-positive@1.0.0')}
${path.join(workspaceWithPrivatePkgs, 'node_modules/.pnpm/is-positive@1.0.0/node_modules/is-positive')}
${path.join(workspaceWithPrivatePkgs, 'packages/public')}
${path.join(workspaceWithPrivatePkgs, 'packages/public/node_modules/.pnpm/is-positive@1.0.0')}`)
${path.join(workspaceWithPrivatePkgs, 'node_modules/.pnpm/is-positive@1.0.0/node_modules/is-positive')}`)
})
test('long parseable list in workspace with private package', async () => {
@@ -271,9 +271,9 @@ test('long parseable list in workspace with private package', async () => {
long: true,
lockfileDir: workspaceWithPrivatePkgs,
})).toBe(`${path.join(workspaceWithPrivatePkgs, 'packages/private')}:private@1.0.0:PRIVATE
${path.join(workspaceWithPrivatePkgs, 'packages/private/node_modules/.pnpm/is-positive@1.0.0')}:is-positive@1.0.0
${path.join(workspaceWithPrivatePkgs, 'node_modules/.pnpm/is-positive@1.0.0/node_modules/is-positive')}:is-positive@1.0.0
${path.join(workspaceWithPrivatePkgs, 'packages/public')}:public@1.0.0
${path.join(workspaceWithPrivatePkgs, 'packages/public/node_modules/.pnpm/is-positive@1.0.0')}:is-positive@1.0.0`)
${path.join(workspaceWithPrivatePkgs, 'node_modules/.pnpm/is-positive@1.0.0/node_modules/is-positive')}:is-positive@1.0.0`)
})
test('JSON list in workspace with private package', async () => {
@@ -317,15 +317,15 @@ test('JSON list in workspace with private package', async () => {
test('parseable list with depth 1', async () => {
expect(await list([fixture], { reportAs: 'parseable', depth: 1, lockfileDir: fixture })).toBe(`${fixture}
${path.join(fixture, 'node_modules/.pnpm/detect-indent@5.0.0')}
${path.join(fixture, 'node_modules/.pnpm/graceful-fs@4.2.2')}
${path.join(fixture, 'node_modules/.pnpm/is-negative@2.1.0')}
${path.join(fixture, 'node_modules/.pnpm/is-positive@3.1.0')}
${path.join(fixture, 'node_modules/.pnpm/make-dir@1.3.0')}
${path.join(fixture, 'node_modules/.pnpm/pify@3.0.0')}
${path.join(fixture, 'node_modules/.pnpm/sort-keys@2.0.0')}
${path.join(fixture, 'node_modules/.pnpm/write-file-atomic@2.4.3')}
${path.join(fixture, 'node_modules/.pnpm/write-json-file@2.3.0')}`)
${path.join(fixture, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')}
${path.join(fixture, 'node_modules/.pnpm/graceful-fs@4.2.2/node_modules/graceful-fs')}
${path.join(fixture, 'node_modules/.pnpm/is-negative@2.1.0/node_modules/is-negative')}
${path.join(fixture, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}
${path.join(fixture, 'node_modules/.pnpm/make-dir@1.3.0/node_modules/make-dir')}
${path.join(fixture, 'node_modules/.pnpm/pify@3.0.0/node_modules/pify')}
${path.join(fixture, 'node_modules/.pnpm/sort-keys@2.0.0/node_modules/sort-keys')}
${path.join(fixture, 'node_modules/.pnpm/write-file-atomic@2.4.3/node_modules/write-file-atomic')}
${path.join(fixture, 'node_modules/.pnpm/write-json-file@2.3.0/node_modules/write-json-file')}`)
})
test('JSON list with depth 1', async () => {
@@ -459,7 +459,7 @@ test('parseable list with depth 1 and dev only', async () => {
reportAs: 'parseable',
})
).toBe(`${fixture}
${path.join(fixture, 'node_modules/.pnpm/is-positive@3.1.0')}`
${path.join(fixture, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}`
)
})
@@ -476,35 +476,35 @@ test('parseable list with depth 1 without unnecessary empty newlines', async ()
reportAs: 'parseable',
}
)).toBe(`${path.join(workspaceWithDifferentDeps, 'packages/bar')}
${path.join(workspaceWithDifferentDeps, 'packages/bar', 'node_modules/.pnpm/is-positive@3.1.0')}`
${path.join(workspaceWithDifferentDeps, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}`
)
})
test('long parseable list with depth 1', async () => {
expect(await list([fixture], { reportAs: 'parseable', depth: 1, lockfileDir: fixture, long: true })).toBe(`${fixture}:fixture@1.0.0
${path.join(fixture, 'node_modules/.pnpm/detect-indent@5.0.0')}:detect-indent@5.0.0
${path.join(fixture, 'node_modules/.pnpm/graceful-fs@4.2.2')}:graceful-fs@4.2.2
${path.join(fixture, 'node_modules/.pnpm/is-negative@2.1.0')}:is-negative@2.1.0
${path.join(fixture, 'node_modules/.pnpm/is-positive@3.1.0')}:is-positive@3.1.0
${path.join(fixture, 'node_modules/.pnpm/make-dir@1.3.0')}:make-dir@1.3.0
${path.join(fixture, 'node_modules/.pnpm/pify@3.0.0')}:pify@3.0.0
${path.join(fixture, 'node_modules/.pnpm/sort-keys@2.0.0')}:sort-keys@2.0.0
${path.join(fixture, 'node_modules/.pnpm/write-file-atomic@2.4.3')}:write-file-atomic@2.4.3
${path.join(fixture, 'node_modules/.pnpm/write-json-file@2.3.0')}:write-json-file@2.3.0`)
${path.join(fixture, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')}:detect-indent@5.0.0
${path.join(fixture, 'node_modules/.pnpm/graceful-fs@4.2.2/node_modules/graceful-fs')}:graceful-fs@4.2.2
${path.join(fixture, 'node_modules/.pnpm/is-negative@2.1.0/node_modules/is-negative')}:is-negative@2.1.0
${path.join(fixture, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}:is-positive@3.1.0
${path.join(fixture, 'node_modules/.pnpm/make-dir@1.3.0/node_modules/make-dir')}:make-dir@1.3.0
${path.join(fixture, 'node_modules/.pnpm/pify@3.0.0/node_modules/pify')}:pify@3.0.0
${path.join(fixture, 'node_modules/.pnpm/sort-keys@2.0.0/node_modules/sort-keys')}:sort-keys@2.0.0
${path.join(fixture, 'node_modules/.pnpm/write-file-atomic@2.4.3/node_modules/write-file-atomic')}:write-file-atomic@2.4.3
${path.join(fixture, 'node_modules/.pnpm/write-json-file@2.3.0/node_modules/write-json-file')}:write-json-file@2.3.0`)
})
test('long parseable list with depth 1 when package has no version', async () => {
expect(await list([fixtureWithNoPkgVersion], { reportAs: 'parseable', depth: 1, lockfileDir: fixtureWithNoPkgVersion, long: true })).toBe(`\
${fixtureWithNoPkgVersion}:fixture
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/detect-indent@5.0.0')}:detect-indent@5.0.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/graceful-fs@4.2.2')}:graceful-fs@4.2.2
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/is-negative@2.1.0')}:is-negative@2.1.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/is-positive@3.1.0')}:is-positive@3.1.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/make-dir@1.3.0')}:make-dir@1.3.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/pify@3.0.0')}:pify@3.0.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/sort-keys@2.0.0')}:sort-keys@2.0.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/write-file-atomic@2.4.3')}:write-file-atomic@2.4.3
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/write-json-file@2.3.0')}:write-json-file@2.3.0`)
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')}:detect-indent@5.0.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/graceful-fs@4.2.2/node_modules/graceful-fs')}:graceful-fs@4.2.2
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/is-negative@2.1.0/node_modules/is-negative')}:is-negative@2.1.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}:is-positive@3.1.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/make-dir@1.3.0/node_modules/make-dir')}:make-dir@1.3.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/pify@3.0.0/node_modules/pify')}:pify@3.0.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/sort-keys@2.0.0/node_modules/sort-keys')}:sort-keys@2.0.0
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/write-file-atomic@2.4.3/node_modules/write-file-atomic')}:write-file-atomic@2.4.3
${path.join(fixtureWithNoPkgVersion, 'node_modules/.pnpm/write-json-file@2.3.0/node_modules/write-json-file')}:write-json-file@2.3.0`)
})
test('long parseable list with depth 1 when package has no name and no version', async () => {
@@ -514,15 +514,15 @@ test('long parseable list with depth 1 when package has no name and no version',
{ reportAs: 'parseable', depth: 1, lockfileDir: fixtureWithNoPkgNameAndNoVersion, long: true }
)
).toBe(`${fixtureWithNoPkgNameAndNoVersion}
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/detect-indent@5.0.0')}:detect-indent@5.0.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/graceful-fs@4.2.2')}:graceful-fs@4.2.2
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/is-negative@2.1.0')}:is-negative@2.1.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/is-positive@3.1.0')}:is-positive@3.1.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/make-dir@1.3.0')}:make-dir@1.3.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/pify@3.0.0')}:pify@3.0.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/sort-keys@2.0.0')}:sort-keys@2.0.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/write-file-atomic@2.4.3')}:write-file-atomic@2.4.3
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/write-json-file@2.3.0')}:write-json-file@2.3.0`
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/detect-indent@5.0.0/node_modules/detect-indent')}:detect-indent@5.0.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/graceful-fs@4.2.2/node_modules/graceful-fs')}:graceful-fs@4.2.2
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/is-negative@2.1.0/node_modules/is-negative')}:is-negative@2.1.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/is-positive@3.1.0/node_modules/is-positive')}:is-positive@3.1.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/make-dir@1.3.0/node_modules/make-dir')}:make-dir@1.3.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/pify@3.0.0/node_modules/pify')}:pify@3.0.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/sort-keys@2.0.0/node_modules/sort-keys')}:sort-keys@2.0.0
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/write-file-atomic@2.4.3/node_modules/write-file-atomic')}:write-file-atomic@2.4.3
${path.join(fixtureWithNoPkgNameAndNoVersion, 'node_modules/.pnpm/write-json-file@2.3.0/node_modules/write-json-file')}:write-json-file@2.3.0`
)
})

View File

@@ -120,6 +120,7 @@ export type ListCommandOptions = Pick<Config,
| 'optional'
| 'production'
| 'selectedProjectsGraph'
| 'modulesDir'
> & Partial<Pick<Config, 'cliOptions'>> & {
alwaysPrintRootPackage?: boolean
depth?: number
@@ -164,6 +165,7 @@ export async function render (
json?: boolean
onlyProjects?: boolean
parseable?: boolean
modulesDir?: string
}
) {
const listOpts = {
@@ -175,6 +177,7 @@ export async function render (
onlyProjects: opts.onlyProjects,
reportAs: (opts.parseable ? 'parseable' : (opts.json ? 'json' : 'tree')) as ('parseable' | 'json' | 'tree'),
showExtraneous: false,
modulesDir: opts.modulesDir,
}
return (params.length > 0)
? listForPackages(params, prefixes, listOpts)