feat: return workspace for resolvedVia for workspace packages (#9293)

* feat: return `workspace` for `resolvedVia`

* chore: update .changeset/shaggy-chefs-reply.md
This commit is contained in:
Brandon Cheng
2025-03-16 20:40:56 -04:00
committed by Zoltan Kochan
parent 36ff4bfaf1
commit 3d52365a6e
4 changed files with 39 additions and 18 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/resolver-base": minor
"@pnpm/npm-resolver": major
---
The `@pnpm/npm-resolver` package can now return `workspace` in the `resolvedVia` field of its results. This will be the case if the resolved package was requested through the `workspace:` protocol or if the wanted dependency's name and specifier match a package in the workspace. Previously, the `resolvedVia` field was always set to `local-filesystem` for workspace packages.

View File

@@ -15,6 +15,7 @@ import {
type WorkspacePackage,
type WorkspacePackages,
type WorkspacePackagesByVersion,
type WorkspaceResolveResult,
} from '@pnpm/resolver-base'
import { LRUCache } from 'lru-cache'
import normalize from 'normalize-path'
@@ -253,7 +254,7 @@ function tryResolveFromWorkspace (
workspacePackages?: WorkspacePackages
injectWorkspacePackages?: boolean
}
): ResolveResult | null {
): WorkspaceResolveResult | null {
if (!wantedDependency.pref?.startsWith('workspace:')) {
return null
}
@@ -284,7 +285,7 @@ function tryResolveFromWorkspacePackages (
projectDir: string
lockfileDir?: string
}
): ResolveResult {
): WorkspaceResolveResult {
const workspacePkgsMatchingName = workspacePackages.get(spec.name)
if (!workspacePkgsMatchingName) {
throw new PnpmError(
@@ -331,7 +332,7 @@ function resolveFromLocalPackage (
projectDir: string
lockfileDir?: string
}
): ResolveResult {
): WorkspaceResolveResult {
let id!: PkgResolutionId
let directory!: string
const localPackageDir = resolveLocalPackageDir(localPackage)
@@ -350,7 +351,7 @@ function resolveFromLocalPackage (
directory,
type: 'directory',
},
resolvedVia: 'local-filesystem',
resolvedVia: 'workspace',
}
}

View File

@@ -1018,7 +1018,7 @@ test('resolve from local directory when it matches the latest version of the pac
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive')
expect(resolveResult!.latest!.split('.').length).toBe(3)
expect(resolveResult!.resolution).toStrictEqual({
@@ -1056,7 +1056,9 @@ test('resolve injected dependency from local directory when it matches the lates
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
// Injected workspace dependencies should still signal that they're resolved
// via the 'workspace' rather than 'local-filesystem'.
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('file:is-positive')
expect(resolveResult!.latest!.split('.').length).toBe(3)
expect(resolveResult!.resolution).toStrictEqual({
@@ -1128,7 +1130,7 @@ test('resolve from local directory when alwaysTryWorkspacePackages is false but
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive')
expect(resolveResult!.resolution).toStrictEqual({
directory: '/home/istvan/src/is-positive',
@@ -1161,7 +1163,7 @@ test('resolve from local directory when alwaysTryWorkspacePackages is false but
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive')
expect(resolveResult!.resolution).toStrictEqual({
directory: '/home/istvan/src/is-positive',
@@ -1247,7 +1249,7 @@ test('preferWorkspacePackages: use version from the workspace even if there is n
expect(resolveResult).toStrictEqual(
expect.objectContaining({
resolvedVia: 'local-filesystem',
resolvedVia: 'workspace',
id: 'link:is-positive',
latest: '3.1.0',
})
@@ -1284,7 +1286,7 @@ test('use local version if it is newer than the latest in the registry', async (
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive')
expect(resolveResult!.latest!.split('.').length).toBe(3)
expect(resolveResult!.resolution).toStrictEqual({
@@ -1335,7 +1337,7 @@ test('resolve from local directory when package is not found in the registry', a
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:../is-positive')
expect(resolveResult!.latest).toBeFalsy()
expect(resolveResult!.resolution).toStrictEqual({
@@ -1386,7 +1388,7 @@ test('resolve from local directory when package is not found in the registry and
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive-2.0.0')
expect(resolveResult!.latest).toBeFalsy()
expect(resolveResult!.resolution).toStrictEqual({
@@ -1423,7 +1425,7 @@ test('resolve from local directory when package is not found in the registry and
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive')
expect(resolveResult!.latest).toBeFalsy()
expect(resolveResult!.resolution).toStrictEqual({
@@ -1474,7 +1476,7 @@ test('resolve from local directory when package is not found in the registry and
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:../is-positive')
expect(resolveResult!.latest).toBeFalsy()
expect(resolveResult!.resolution).toStrictEqual({
@@ -1511,7 +1513,7 @@ test('resolve from local directory when the requested version is not found in th
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:../is-positive')
expect(resolveResult!.latest).toBeFalsy()
expect(resolveResult!.resolution).toStrictEqual({
@@ -1544,7 +1546,7 @@ test('workspace protocol: resolve from local directory even when it does not mat
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive')
expect(resolveResult!.latest).toBeFalsy()
expect(resolveResult!.resolution).toStrictEqual({
@@ -1581,7 +1583,7 @@ test('workspace protocol: resolve from local package that has a pre-release vers
]),
})
expect(resolveResult!.resolvedVia).toBe('local-filesystem')
expect(resolveResult!.resolvedVia).toBe('workspace')
expect(resolveResult!.id).toBe('link:is-positive')
expect(resolveResult!.latest).toBeFalsy()
expect(resolveResult!.resolution).toStrictEqual({

View File

@@ -40,7 +40,19 @@ export interface ResolveResult {
manifest?: DependencyManifest
normalizedPref?: string // is null for npm-hosted dependencies
resolution: Resolution
resolvedVia: 'npm-registry' | 'git-repository' | 'local-filesystem' | 'url' | string
resolvedVia: 'npm-registry' | 'git-repository' | 'local-filesystem' | 'workspace' | 'url' | string
}
/**
* A dependency on a workspace package.
*/
export interface WorkspaceResolveResult extends ResolveResult {
/**
* 'workspace' will be returned for workspace: protocol dependencies or a
* package in the workspace that matches the wanted dependency's name and
* version range.
*/
resolvedVia: 'workspace'
}
export interface WorkspacePackage {