mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
fix(filtering): support linked-workspace- packages=false in workspace filtering
Pass the linkedWorkspacePackages config to the pkg-graph, only select packages that are explicitly referred to as workspace:... when this setting is on. Fixes #2625 PR #2626
This commit is contained in:
6
.changeset/modern-cheetahs-doubt.md
Normal file
6
.changeset/modern-cheetahs-doubt.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/filter-workspace-packages": minor
|
||||
"pkgs-graph": minor
|
||||
---
|
||||
|
||||
Support linkedWorkspacePackages=false.
|
||||
5
.changeset/perfect-walls-run.md
Normal file
5
.changeset/perfect-walls-run.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
When `link-workspace-packages` is `false`, filtering by dependencies/dependents should ignore any packages that are not specified via `workspace:` ranges.
|
||||
@@ -18,13 +18,17 @@ interface Graph {
|
||||
|
||||
export async function readProjects (
|
||||
workspaceDir: string,
|
||||
pkgSelectors: PackageSelector[]
|
||||
pkgSelectors: PackageSelector[],
|
||||
opts?: {
|
||||
linkWorkspacePackages?: boolean,
|
||||
}
|
||||
) {
|
||||
const allProjects = await findWorkspacePackages(workspaceDir, {})
|
||||
const { selectedProjectsGraph } = await filterPkgsBySelectorObjects(
|
||||
allProjects,
|
||||
pkgSelectors,
|
||||
{
|
||||
linkWorkspacePackages: opts?.linkWorkspacePackages,
|
||||
workspaceDir,
|
||||
}
|
||||
)
|
||||
@@ -35,6 +39,7 @@ export async function filterPackages<T> (
|
||||
pkgs: Array<Package & T>,
|
||||
filter: string[],
|
||||
opts: {
|
||||
linkWorkspacePackages?: boolean,
|
||||
prefix: string,
|
||||
workspaceDir: string,
|
||||
}
|
||||
@@ -52,13 +57,14 @@ export async function filterPkgsBySelectorObjects<T> (
|
||||
pkgs: Array<Package & T>,
|
||||
packageSelectors: PackageSelector[],
|
||||
opts: {
|
||||
linkWorkspacePackages?: boolean,
|
||||
workspaceDir: string,
|
||||
}
|
||||
): Promise<{
|
||||
selectedProjectsGraph: PackageGraph<T>,
|
||||
unmatchedFilters: string[],
|
||||
}> {
|
||||
const { graph } = createPkgGraph<T>(pkgs)
|
||||
const { graph } = createPkgGraph<T>(pkgs, { linkWorkspacePackages: opts.linkWorkspacePackages })
|
||||
if (packageSelectors && packageSelectors.length) {
|
||||
return filterGraph(graph, packageSelectors, {
|
||||
workspaceDir: opts.workspaceDir,
|
||||
|
||||
@@ -27,7 +27,9 @@ export type PackageNode<T> = {
|
||||
dependencies: string[],
|
||||
}
|
||||
|
||||
export default function<T> (pkgs: Array<Package & T>): {
|
||||
export default function<T> (pkgs: Array<Package & T>, opts?: {
|
||||
linkWorkspacePackages?: boolean
|
||||
}): {
|
||||
graph: {[id: string]: PackageNode<T>},
|
||||
unmatched: Array<{pkgName: string, range: string}>,
|
||||
} {
|
||||
@@ -54,8 +56,9 @@ export default function<T> (pkgs: Array<Package & T>): {
|
||||
.map(depName => {
|
||||
let spec!: { fetchSpec: string, type: string }
|
||||
let rawSpec = dependencies[depName]
|
||||
const isWorkspaceSpec = rawSpec.startsWith('workspace:')
|
||||
try {
|
||||
if (rawSpec.startsWith('workspace:')) {
|
||||
if (isWorkspaceSpec) {
|
||||
rawSpec = rawSpec.substr(10)
|
||||
}
|
||||
spec = npa.resolve(depName, rawSpec, pkg.dir)
|
||||
@@ -77,6 +80,13 @@ export default function<T> (pkgs: Array<Package & T>): {
|
||||
if (!pkgs.length) return ''
|
||||
const versions = pkgs.filter(({ manifest }) => manifest.version)
|
||||
.map(pkg => pkg.manifest.version) as string[]
|
||||
|
||||
// explicitly check if false, backwards-compatibility (can be undefined)
|
||||
const strictWorkspaceMatching = opts?.linkWorkspacePackages === false && !isWorkspaceSpec
|
||||
if (strictWorkspaceMatching) {
|
||||
unmatched.push({ pkgName: depName, range: rawSpec })
|
||||
return ''
|
||||
}
|
||||
if (versions.includes(rawSpec)) {
|
||||
const matchedPkg = pkgs.find(pkg => pkg.manifest.name === depName && pkg.manifest.version === rawSpec)
|
||||
return matchedPkg!.dir
|
||||
|
||||
@@ -7,6 +7,7 @@ const BAR1_PATH = pathResolve('/zkochan/src/bar')
|
||||
const FOO1_PATH = pathResolve('/zkochan/src/foo')
|
||||
const BAR2_PATH = pathResolve('/zkochan/src/bar@2')
|
||||
const FOO2_PATH = pathResolve('/zkochan/src/foo@2')
|
||||
const BAR3_PATH = pathResolve('/zkochan/src/bar@3')
|
||||
|
||||
test('create package graph', t => {
|
||||
const result = createPkgGraph([
|
||||
@@ -319,17 +320,119 @@ test('create package graph ignoring the workspace protocol', t => {
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('create package graph respects linked-workspace-packages = false', t => {
|
||||
const result = createPkgGraph([
|
||||
{
|
||||
dir: BAR1_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'foo': 'workspace:*',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '1.0.0',
|
||||
},
|
||||
},
|
||||
{
|
||||
dir: FOO1_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
bar: '^10.0.0',
|
||||
},
|
||||
name: 'foo',
|
||||
version: '1.0.1',
|
||||
},
|
||||
},
|
||||
{
|
||||
dir: BAR2_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
foo: '1.0.1',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '2.0.0',
|
||||
},
|
||||
},
|
||||
{
|
||||
dir: BAR3_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'foo': 'workspace:~1.0.0',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '3.0.0',
|
||||
},
|
||||
},
|
||||
], { linkWorkspacePackages: false })
|
||||
t.deepEqual(result.unmatched, [{ pkgName: 'bar', range: '^10.0.0' }, { pkgName: 'foo', range: '1.0.1' }])
|
||||
t.deepEqual(result.graph, {
|
||||
[BAR1_PATH]: {
|
||||
dependencies: [FOO1_PATH],
|
||||
package: {
|
||||
dir: BAR1_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'foo': 'workspace:*',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '1.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
[FOO1_PATH]: {
|
||||
dependencies: [],
|
||||
package: {
|
||||
dir: FOO1_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
bar: '^10.0.0',
|
||||
},
|
||||
name: 'foo',
|
||||
version: '1.0.1',
|
||||
},
|
||||
},
|
||||
},
|
||||
[BAR2_PATH]: {
|
||||
// no workspace range, so this shouldn't have any
|
||||
// workspace dependencies
|
||||
dependencies: [],
|
||||
package: {
|
||||
dir: BAR2_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
foo: '1.0.1',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '2.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
[BAR3_PATH]: {
|
||||
dependencies: [FOO1_PATH],
|
||||
package: {
|
||||
dir: BAR3_PATH,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
foo: 'workspace:~1.0.0',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '3.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('* matches prerelease versions', t => {
|
||||
const result = createPkgGraph([
|
||||
{
|
||||
dir: BAR1_PATH,
|
||||
manifest: {
|
||||
name: 'bar',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'foo': '*',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '1.0.0',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -347,12 +450,11 @@ test('* matches prerelease versions', t => {
|
||||
package: {
|
||||
dir: BAR1_PATH,
|
||||
manifest: {
|
||||
name: 'bar',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'foo': '*',
|
||||
},
|
||||
name: 'bar',
|
||||
version: '1.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -186,6 +186,57 @@ test('recursive list --filter', async (t) => {
|
||||
]),
|
||||
}, [])
|
||||
|
||||
test('recursive list --filter link-workspace-packages=false', async (t) => {
|
||||
const projects = preparePackages(t, [
|
||||
{
|
||||
dependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
'project-2': 'workspace:*',
|
||||
},
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
name: 'project-2',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
name: 'is-positive',
|
||||
version: '1.0.0',
|
||||
},
|
||||
])
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
...await readProjects(process.cwd(), [], { linkWorkspacePackages: false }),
|
||||
dir: process.cwd(),
|
||||
linkWorkspacePackages: false,
|
||||
recursive: true,
|
||||
workspaceDir: process.cwd(),
|
||||
})
|
||||
|
||||
const output = await list.handler({
|
||||
...DEFAULT_OPTS,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
...await readProjects(process.cwd(), [
|
||||
{ includeDependencies: true, namePattern: 'project-1' },
|
||||
], { linkWorkspacePackages: false }),
|
||||
}, [])
|
||||
|
||||
t.equal(stripAnsi(output as unknown as string), stripIndent`
|
||||
Legend: production dependency, optional only, dev only
|
||||
|
||||
project-1@1.0.0 ${path.resolve('project-1')}
|
||||
|
||||
dependencies:
|
||||
is-positive 1.0.0
|
||||
project-2 link:../project-2
|
||||
|
||||
`)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.equal(stripAnsi(output as unknown as string), stripIndent`
|
||||
Legend: production dependency, optional only, dev only
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ export default async function run (inputArgv: string[]) {
|
||||
return
|
||||
}
|
||||
const filterResults = await filterPackages(allProjects, config.filter ?? [], {
|
||||
linkWorkspacePackages: !!config.linkWorkspacePackages,
|
||||
prefix: process.cwd(),
|
||||
workspaceDir: wsDir,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user