mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-23 23:29:17 -05:00
fix: pnpm link --global <pkg> should not change the type of the dependency (#5512)
Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
5
.changeset/lazy-days-run.md
Normal file
5
.changeset/lazy-days-run.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/types": minor
|
||||
---
|
||||
|
||||
New type exported: DependenciesOrPeersField
|
||||
6
.changeset/odd-peas-fetch.md
Normal file
6
.changeset/odd-peas-fetch.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"pnpm": patch
|
||||
"@pnpm/core": patch
|
||||
---
|
||||
|
||||
`pnpm link --global <pkg>` should not change the type of the dependency [#5478](https://github.com/pnpm/pnpm/issues/5478).
|
||||
5
.changeset/ten-dancers-happen.md
Normal file
5
.changeset/ten-dancers-happen.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/manifest-utils": minor
|
||||
---
|
||||
|
||||
New function exported: `getDependencyTypeFromManifest()`.
|
||||
@@ -15,6 +15,7 @@ import { logger, streamParser } from '@pnpm/logger'
|
||||
import {
|
||||
getPref,
|
||||
getSpecFromPackageManifest,
|
||||
getDependencyTypeFromManifest,
|
||||
guessDependencyType,
|
||||
PackageSpecObject,
|
||||
updateProjectManifestObject,
|
||||
@@ -74,12 +75,14 @@ export async function link (
|
||||
throw new PnpmError('INVALID_PACKAGE_NAME', `Package in ${linkFromPath} must have a name field to be linked`)
|
||||
}
|
||||
|
||||
const targetDependencyType = getDependencyTypeFromManifest(opts.manifest, manifest.name) ?? opts.targetDependenciesField
|
||||
|
||||
specsToUpsert.push({
|
||||
alias: manifest.name,
|
||||
pref: getPref(manifest.name, manifest.name, manifest.version, {
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
}),
|
||||
saveType: (opts.targetDependenciesField ?? (ctx.manifest && guessDependencyType(manifest.name, ctx.manifest))) as DependenciesField,
|
||||
saveType: (targetDependencyType ?? (ctx.manifest && guessDependencyType(manifest.name, ctx.manifest))) as DependenciesField,
|
||||
})
|
||||
|
||||
const packagePath = normalize(path.relative(opts.dir, linkFromPath))
|
||||
@@ -108,8 +111,9 @@ export async function link (
|
||||
for (const { alias, manifest, path } of linkedPkgs) {
|
||||
// TODO: cover with test that linking reports with correct dependency types
|
||||
const stu = specsToUpsert.find((s) => s.alias === manifest.name)
|
||||
const targetDependencyType = getDependencyTypeFromManifest(opts.manifest, manifest.name) ?? opts.targetDependenciesField
|
||||
await symlinkDirectRootDependency(path, destModules, alias, {
|
||||
fromDependenciesField: stu?.saveType ?? opts.targetDependenciesField,
|
||||
fromDependenciesField: stu?.saveType ?? (targetDependencyType as DependenciesField),
|
||||
linkedPackage: manifest,
|
||||
prefix: opts.dir,
|
||||
})
|
||||
|
||||
@@ -210,6 +210,30 @@ test('throws error is package name is not defined', async () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('link should not change the type of the dependency', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
const linkedPkgName = 'hello-world-js-bin'
|
||||
const linkedPkgPath = path.resolve('..', linkedPkgName)
|
||||
|
||||
f.copy(linkedPkgName, linkedPkgPath)
|
||||
await link([`../${linkedPkgName}`], path.join(process.cwd(), 'node_modules'), await testDefaults({
|
||||
dir: process.cwd(),
|
||||
manifest: {
|
||||
devDependencies: {
|
||||
'@pnpm.e2e/hello-world-js-bin': '*',
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
await project.isExecutable('.bin/hello-world-js-bin')
|
||||
|
||||
const wantedLockfile = await project.readLockfile()
|
||||
expect(wantedLockfile.devDependencies).toStrictEqual({
|
||||
'@pnpm.e2e/hello-world-js-bin': 'link:../hello-world-js-bin',
|
||||
})
|
||||
})
|
||||
|
||||
// test.skip('relative link when an external lockfile is used', async () => {
|
||||
// const projects = prepare(t, [
|
||||
// {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Dependencies, ProjectManifest } from '@pnpm/types'
|
||||
import { Dependencies, DependenciesField, ProjectManifest } from '@pnpm/types'
|
||||
|
||||
export function getAllDependenciesFromManifest (
|
||||
pkg: Pick<ProjectManifest, 'devDependencies' | 'dependencies' | 'optionalDependencies'>
|
||||
pkg: Pick<ProjectManifest, DependenciesField>
|
||||
): Dependencies {
|
||||
return {
|
||||
...pkg.devDependencies,
|
||||
|
||||
12
packages/manifest-utils/src/getDependencyTypeFromManifest.ts
Normal file
12
packages/manifest-utils/src/getDependencyTypeFromManifest.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ProjectManifest, DependenciesOrPeersField } from '@pnpm/types'
|
||||
|
||||
export function getDependencyTypeFromManifest (
|
||||
manifest: Pick<ProjectManifest, DependenciesOrPeersField>,
|
||||
depName: string
|
||||
): DependenciesOrPeersField | null {
|
||||
if (manifest.optionalDependencies?.[depName]) return 'optionalDependencies'
|
||||
if (manifest.dependencies?.[depName]) return 'dependencies'
|
||||
if (manifest.devDependencies?.[depName]) return 'devDependencies'
|
||||
if (manifest.peerDependencies?.[depName]) return 'peerDependencies'
|
||||
return null
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ProjectManifest } from '@pnpm/types'
|
||||
import { ProjectManifest, DependenciesOrPeersField } from '@pnpm/types'
|
||||
|
||||
export function getSpecFromPackageManifest (
|
||||
manifest: Pick<ProjectManifest, 'devDependencies' | 'dependencies' | 'optionalDependencies' | 'peerDependencies'>,
|
||||
manifest: Pick<ProjectManifest, DependenciesOrPeersField>,
|
||||
depName: string
|
||||
) {
|
||||
return manifest.optionalDependencies?.[depName] ??
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getSpecFromPackageManifest } from './getSpecFromPackageManifest'
|
||||
|
||||
export * from './getPref'
|
||||
export * from './updateProjectManifestObject'
|
||||
export * from './getDependencyTypeFromManifest'
|
||||
|
||||
export { getSpecFromPackageManifest }
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { getDependencyTypeFromManifest } from '@pnpm/manifest-utils'
|
||||
|
||||
test('getDependencyTypeFromManifest()', () => {
|
||||
expect(
|
||||
getDependencyTypeFromManifest({
|
||||
dependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
}, 'foo')).toEqual('dependencies')
|
||||
|
||||
expect(
|
||||
getDependencyTypeFromManifest({
|
||||
devDependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
}, 'foo')).toEqual('devDependencies')
|
||||
|
||||
expect(
|
||||
getDependencyTypeFromManifest({
|
||||
optionalDependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
}, 'foo')).toEqual('optionalDependencies')
|
||||
|
||||
expect(
|
||||
getDependencyTypeFromManifest({
|
||||
peerDependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
}, 'foo')).toEqual('peerDependencies')
|
||||
|
||||
expect(
|
||||
getDependencyTypeFromManifest({
|
||||
peerDependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
}, 'bar')).toEqual(null)
|
||||
})
|
||||
@@ -1,5 +1,7 @@
|
||||
export type DependenciesField = 'optionalDependencies' | 'dependencies' | 'devDependencies'
|
||||
|
||||
export type DependenciesOrPeersField = DependenciesField | 'peerDependencies'
|
||||
|
||||
// NOTE: The order in this array is important.
|
||||
export const DEPENDENCIES_FIELDS: DependenciesField[] = [
|
||||
'optionalDependencies',
|
||||
|
||||
Reference in New Issue
Block a user