mirror of
https://github.com/pnpm/pnpm.git
synced 2026-06-01 12:41:16 -04:00
fix(config): warn when package.json has a legacy "pnpm" field with migrated settings (#11680)
* fix(config): warn when package.json has a legacy "pnpm" field In v11, pnpm stopped reading settings from the `pnpm` field of package.json (#10086). Most former pnpm-field settings now live in `pnpm-workspace.yaml`; a few (e.g. `onlyBuiltDependencies`, `executionEnv`) were removed entirely. Until now the old field was silently ignored, so users upgrading from v10 had no signal that their overrides or patched dependencies had stopped taking effect. Emit a warning whenever the `pnpm` field contains any key that pnpm no longer reads from package.json. The check is an allowlist (only `pnpm.app`, consumed by `pnpm pack-app`, is still active), so the warning won't go stale as new settings are added or removed in future versions. The message points users at https://pnpm.io/settings rather than prescribing a single fix, since the new home depends on the key. Closes #11677. * fix(config): only warn for migrated pnpm-field keys, not unrelated ones Previously the warning fired for every key under `pnpm` except `app`, which would surface false positives for third-party tooling that piggybacks on the `pnpm` namespace. Switch to an explicit denylist of the v10 settings that moved to pnpm-workspace.yaml, matching the PR's stated contract. --------- Co-authored-by: Damon <damon@deeplearning.ai> Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
6
.changeset/warn-deprecated-pnpm-field-11677.md
Normal file
6
.changeset/warn-deprecated-pnpm-field-11677.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/config.reader": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Warn when `package.json` contains a legacy `pnpm` field with settings pnpm no longer reads from `package.json` (e.g. `pnpm.overrides`, `pnpm.patchedDependencies`). Previously these were silently ignored after the upgrade from v10, leaving users unaware that their overrides/patched dependencies had stopped taking effect [#11677](https://github.com/pnpm/pnpm/issues/11677).
|
||||
@@ -404,6 +404,10 @@ export async function getConfig (opts: {
|
||||
if (pnpmConfig.rootProjectManifest.workspaces?.length && !pnpmConfig.workspaceDir) {
|
||||
warnings.push('The "workspaces" field in package.json is not supported by pnpm. Create a "pnpm-workspace.yaml" file instead.')
|
||||
}
|
||||
const ignoredPnpmFieldKeys = getIgnoredPnpmFieldKeys(pnpmConfig.rootProjectManifest)
|
||||
if (ignoredPnpmFieldKeys.length > 0) {
|
||||
warnings.push(`The "pnpm" field in package.json is no longer read by pnpm. The following keys were ignored: ${ignoredPnpmFieldKeys.map(k => `"pnpm.${k}"`).join(', ')}. See https://pnpm.io/settings for the new home of each setting.`)
|
||||
}
|
||||
const wantedPmResult = getWantedPackageManager(pnpmConfig.rootProjectManifest)
|
||||
if (wantedPmResult.pm) {
|
||||
pnpmConfig.wantedPackageManager = wantedPmResult.pm
|
||||
@@ -750,6 +754,38 @@ function getWantedPackageManager (manifest: ProjectManifest): { pm?: WantedPacka
|
||||
return { warnings }
|
||||
}
|
||||
|
||||
// Settings that used to be read from the `pnpm` field of `package.json` in v10
|
||||
// but moved to `pnpm-workspace.yaml` in v11. Keys not in this set (e.g. `app`,
|
||||
// or anything set by third-party tooling that piggybacks on the `pnpm` namespace)
|
||||
// are left alone to avoid false-positive warnings.
|
||||
const MIGRATED_PNPM_FIELD_KEYS = new Set<string>([
|
||||
'allowBuilds',
|
||||
'allowedDeprecatedVersions',
|
||||
'allowUnusedPatches',
|
||||
'auditConfig',
|
||||
'configDependencies',
|
||||
'executionEnv',
|
||||
'ignoredOptionalDependencies',
|
||||
'neverBuiltDependencies',
|
||||
'onlyBuiltDependencies',
|
||||
'onlyBuiltDependenciesFile',
|
||||
'overrides',
|
||||
'packageExtensions',
|
||||
'patchedDependencies',
|
||||
'peerDependencyRules',
|
||||
'requiredScripts',
|
||||
'supportedArchitectures',
|
||||
'updateConfig',
|
||||
])
|
||||
|
||||
function getIgnoredPnpmFieldKeys (manifest: ProjectManifest): string[] {
|
||||
const legacyField = (manifest as { pnpm?: unknown }).pnpm
|
||||
if (legacyField == null || typeof legacyField !== 'object' || Array.isArray(legacyField)) {
|
||||
return []
|
||||
}
|
||||
return Object.keys(legacyField as Record<string, unknown>).filter(k => MIGRATED_PNPM_FIELD_KEYS.has(k))
|
||||
}
|
||||
|
||||
export function parsePackageManager (packageManager: string): { name: string, version: string | undefined } {
|
||||
if (!packageManager.includes('@')) return { name: packageManager, version: undefined }
|
||||
const [name, pmReference] = packageManager.split('@')
|
||||
|
||||
10
config/reader/test/fixtures/pkg-with-legacy-pnpm-field/package.json
vendored
Normal file
10
config/reader/test/fixtures/pkg-with-legacy-pnpm-field/package.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"is-odd": "patches/is-odd.patch"
|
||||
}
|
||||
}
|
||||
}
|
||||
7
config/reader/test/fixtures/pkg-with-pnpm-app-field/package.json
vendored
Normal file
7
config/reader/test/fixtures/pkg-with-pnpm-app-field/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"pnpm": {
|
||||
"app": {
|
||||
"entry": "dist/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
5
config/reader/test/fixtures/pkg-with-unknown-pnpm-field/package.json
vendored
Normal file
5
config/reader/test/fixtures/pkg-with-unknown-pnpm-field/package.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"pnpm": {
|
||||
"foo": "bar"
|
||||
}
|
||||
}
|
||||
@@ -1668,6 +1668,47 @@ test('do not return a warning if a package.json has workspaces field and there i
|
||||
expect(warnings).toStrictEqual([])
|
||||
})
|
||||
|
||||
test('return a warning if a package.json has a legacy "pnpm" field with ignored settings', async () => {
|
||||
const prefix = f.find('pkg-with-legacy-pnpm-field')
|
||||
const { warnings } = await getConfig({
|
||||
cliOptions: { dir: prefix },
|
||||
packageManager: {
|
||||
name: 'pnpm',
|
||||
version: '1.0.0',
|
||||
},
|
||||
})
|
||||
|
||||
expect(warnings).toStrictEqual([
|
||||
'The "pnpm" field in package.json is no longer read by pnpm. The following keys were ignored: "pnpm.overrides", "pnpm.patchedDependencies". See https://pnpm.io/settings for the new home of each setting.',
|
||||
])
|
||||
})
|
||||
|
||||
test('do not return a warning if a package.json "pnpm" field only contains keys that are still actively read (e.g. "pnpm.app")', async () => {
|
||||
const prefix = f.find('pkg-with-pnpm-app-field')
|
||||
const { warnings } = await getConfig({
|
||||
cliOptions: { dir: prefix },
|
||||
packageManager: {
|
||||
name: 'pnpm',
|
||||
version: '1.0.0',
|
||||
},
|
||||
})
|
||||
|
||||
expect(warnings).toStrictEqual([])
|
||||
})
|
||||
|
||||
test('do not return a warning if a package.json "pnpm" field only contains keys unrelated to migrated settings (e.g. set by third-party tooling)', async () => {
|
||||
const prefix = f.find('pkg-with-unknown-pnpm-field')
|
||||
const { warnings } = await getConfig({
|
||||
cliOptions: { dir: prefix },
|
||||
packageManager: {
|
||||
name: 'pnpm',
|
||||
version: '1.0.0',
|
||||
},
|
||||
})
|
||||
|
||||
expect(warnings).toStrictEqual([])
|
||||
})
|
||||
|
||||
test('read PNPM_HOME defined in environment variables', async () => {
|
||||
const oldEnv = process.env
|
||||
const homeDir = './specified-dir'
|
||||
|
||||
Reference in New Issue
Block a user