feat(add): pnpm add should use the default catalog (#8870)

close #8640
This commit is contained in:
martinkors
2024-12-16 02:10:24 +01:00
committed by GitHub
parent ac5b9d8e16
commit c0895e8b12
4 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/core": minor
"pnpm": minor
---
`pnpm add` will now check if the added dependency is in the default workspace catalog. If the added dependency is present in the default catalog and the version requirement of the added dependency matches the default catalog's version, then the `pnpm add` will use the `catalog:` protocol. Note that if no version is specified in the `pnpm add` it will match the version described in the default catalog. If the added dependency does not match the default catalog's version it will use the default `pnpm add` behavior [#8640](https://github.com/pnpm/pnpm/issues/8640).

View File

@@ -658,6 +658,7 @@ Note that in CI environments, this setting is enabled by default.`,
updateWorkspaceDependencies: project.update,
preferredSpecs,
overrides: opts.overrides,
defaultCatalog: opts.catalogs?.default,
})
projectsToInstall.push({
pruneDirectDependencies: false,

View File

@@ -2,6 +2,7 @@ import { parseWantedDependency } from '@pnpm/parse-wanted-dependency'
import { type Dependencies } from '@pnpm/types'
import { whichVersionIsPinned } from '@pnpm/which-version-is-pinned'
import { type PinnedVersion, type WantedDependency } from '@pnpm/resolve-dependencies/lib/getWantedDependencies'
import { type Catalog } from '@pnpm/catalogs.types'
export function parseWantedDependencies (
rawWantedDependencies: string[],
@@ -16,6 +17,7 @@ export function parseWantedDependencies (
overrides?: Record<string, string>
updateWorkspaceDependencies?: boolean
preferredSpecs?: Record<string, string>
defaultCatalog?: Catalog
}
): WantedDependency[] {
return rawWantedDependencies
@@ -28,6 +30,13 @@ export function parseWantedDependencies (
if (!opts.allowNew && (!alias || !opts.currentPrefs[alias])) {
return null
}
if (alias && opts.defaultCatalog?.[alias] && (
(!opts.currentPrefs[alias] && pref === undefined) ||
opts.defaultCatalog[alias] === pref ||
opts.defaultCatalog[alias] === opts.currentPrefs[alias]
)) {
pref = 'catalog:'
}
if (alias && opts.currentPrefs[alias]) {
if (!pref) {
pref = (opts.currentPrefs[alias].startsWith('workspace:') && opts.updateWorkspaceDependencies === true)

View File

@@ -543,6 +543,95 @@ describe('add', () => {
packages: { 'is-positive@1.0.0': expect.objectContaining({}) },
}))
})
test('adding no specific version will use catalog if present', async () => {
const { options, projects, readLockfile } = preparePackagesAndReturnObjects([{
name: 'project1',
dependencies: {},
}])
const updatedManifest = await addDependenciesToPackage(
projects['project1' as ProjectId],
['is-positive'],
{
...options,
lockfileOnly: true,
allowNew: true,
catalogs: {
default: { 'is-positive': '1.0.0' },
},
})
expect(updatedManifest).toEqual({
name: 'project1',
dependencies: {
'is-positive': 'catalog:',
},
})
expect(readLockfile()).toEqual(expect.objectContaining({
catalogs: { default: { 'is-positive': { specifier: '1.0.0', version: '1.0.0' } } },
packages: { 'is-positive@1.0.0': expect.objectContaining({}) },
}))
})
test('adding specific version equal to catalog version will use catalog if present', async () => {
const { options, projects, readLockfile } = preparePackagesAndReturnObjects([{
name: 'project1',
dependencies: {},
}])
const updatedManifest = await addDependenciesToPackage(
projects['project1' as ProjectId],
['is-positive@1.0.0'],
{
...options,
lockfileOnly: true,
allowNew: true,
catalogs: {
default: { 'is-positive': '1.0.0' },
},
})
expect(updatedManifest).toEqual({
name: 'project1',
dependencies: {
'is-positive': 'catalog:',
},
})
expect(readLockfile()).toEqual(expect.objectContaining({
catalogs: { default: { 'is-positive': { specifier: '1.0.0', version: '1.0.0' } } },
packages: { 'is-positive@1.0.0': expect.objectContaining({}) },
}))
})
test('adding different version than the catalog will not use catalog', async () => {
const { options, projects, readLockfile } = preparePackagesAndReturnObjects([{
name: 'project1',
dependencies: {},
}])
const updatedManifest = await addDependenciesToPackage(
projects['project1' as ProjectId],
['is-positive@2.0.0'],
{
...options,
lockfileOnly: true,
allowNew: true,
catalogs: {
default: { 'is-positive': '1.0.0' },
},
})
expect(updatedManifest).toEqual({
name: 'project1',
dependencies: {
'is-positive': '2.0.0',
},
})
expect(readLockfile()).toEqual(expect.objectContaining({
packages: { 'is-positive@2.0.0': expect.objectContaining({}) },
}))
})
})
// The 'pnpm update' command should eventually support updates of dependencies