feat: pnpm init writes devEngines.packageManager field (#11283)

* feat: pnpm init writes devEngines.packageManager field

Replaces the flat "packageManager" field with a "devEngines.packageManager"
entry, using a caret range and onFail: "download" so the declared pnpm
version auto-updates on install.

* fix: update workspace/commands/src/init.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Zoltan Kochan
2026-04-17 13:52:19 +02:00
committed by GitHub
parent ff7733ce21
commit 1c95cb6392
3 changed files with 23 additions and 4 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/workspace.commands": minor
"pnpm": minor
---
`pnpm init` now writes a `devEngines.packageManager` field instead of the `packageManager` field when `init-package-manager` is enabled.

View File

@@ -39,7 +39,7 @@ export function help (): string {
name: '--init-type <commonjs|module>',
},
{
description: 'Pin the project to the current pnpm version by adding a "packageManager" field to package.json',
description: 'Declare a pnpm version range via "devEngines.packageManager" in package.json and auto-download pnpm when it is missing',
name: '--init-package-manager',
},
{
@@ -103,7 +103,14 @@ export async function handler (opts: InitOptions, params?: string[]): Promise<st
const initConfig = getInitConfig(opts)
const packageJson = { ...manifest, ...initConfig }
if (opts.initPackageManager) {
packageJson.packageManager = `pnpm@${packageManager.version}`
packageJson.devEngines = {
...packageJson.devEngines,
packageManager: {
name: 'pnpm',
version: `^${packageManager.version}`,
onFail: 'download',
},
}
}
const priority = Object.fromEntries([
'name',
@@ -115,7 +122,7 @@ export async function handler (opts: InitOptions, params?: string[]): Promise<st
'keywords',
'author',
'license',
'packageManager',
'devEngines',
].map((key, index) => [key, index]))
const sortedPackageJson = sortKeysByPriority({ priority }, packageJson)
await writeProjectManifest(manifestPath, sortedPackageJson, {

View File

@@ -73,7 +73,12 @@ test('init a new package.json with init-package-manager=true', async () => {
await init.handler({ cliOptions: {}, initPackageManager: true })
const manifest = loadJsonFileSync<ProjectManifest>(path.resolve('package.json'))
expect(manifest).toBeTruthy()
expect(manifest.packageManager).toBeTruthy()
expect(manifest).not.toHaveProperty('packageManager')
expect(manifest.devEngines?.packageManager).toEqual({
name: 'pnpm',
version: expect.stringMatching(/^\^\d+\.\d+\.\d+/),
onFail: 'download',
})
})
test('init a new package.json with init-package-manager=false', async () => {
@@ -82,6 +87,7 @@ test('init a new package.json with init-package-manager=false', async () => {
const manifest = loadJsonFileSync<ProjectManifest>(path.resolve('package.json'))
expect(manifest).toBeTruthy()
expect(manifest).not.toHaveProperty('packageManager')
expect(manifest).not.toHaveProperty('devEngines')
})
test('init a new package.json with init-type=module', async () => {