diff --git a/.changeset/warn-deprecated-pnpm-field-11677.md b/.changeset/warn-deprecated-pnpm-field-11677.md new file mode 100644 index 0000000000..0c177c42ea --- /dev/null +++ b/.changeset/warn-deprecated-pnpm-field-11677.md @@ -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). diff --git a/config/reader/src/index.ts b/config/reader/src/index.ts index b0cc36a4ef..1d8eb41f37 100644 --- a/config/reader/src/index.ts +++ b/config/reader/src/index.ts @@ -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([ + '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).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('@') diff --git a/config/reader/test/fixtures/pkg-with-legacy-pnpm-field/package.json b/config/reader/test/fixtures/pkg-with-legacy-pnpm-field/package.json new file mode 100644 index 0000000000..adcad06407 --- /dev/null +++ b/config/reader/test/fixtures/pkg-with-legacy-pnpm-field/package.json @@ -0,0 +1,10 @@ +{ + "pnpm": { + "overrides": { + "lodash": "^4.17.21" + }, + "patchedDependencies": { + "is-odd": "patches/is-odd.patch" + } + } +} diff --git a/config/reader/test/fixtures/pkg-with-pnpm-app-field/package.json b/config/reader/test/fixtures/pkg-with-pnpm-app-field/package.json new file mode 100644 index 0000000000..9cfaa842a7 --- /dev/null +++ b/config/reader/test/fixtures/pkg-with-pnpm-app-field/package.json @@ -0,0 +1,7 @@ +{ + "pnpm": { + "app": { + "entry": "dist/index.js" + } + } +} diff --git a/config/reader/test/fixtures/pkg-with-unknown-pnpm-field/package.json b/config/reader/test/fixtures/pkg-with-unknown-pnpm-field/package.json new file mode 100644 index 0000000000..3e90c1aada --- /dev/null +++ b/config/reader/test/fixtures/pkg-with-unknown-pnpm-field/package.json @@ -0,0 +1,5 @@ +{ + "pnpm": { + "foo": "bar" + } +} diff --git a/config/reader/test/index.ts b/config/reader/test/index.ts index cee7de949f..a4403fc924 100644 --- a/config/reader/test/index.ts +++ b/config/reader/test/index.ts @@ -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'