mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-27 18:46:18 -04:00
fix: match read/write priority when both pnpm-workspace.yaml and .npmrc exist (#10073)
* fix: match read/write priority when both pnpm-workspace.yaml and .npmrc exist * chore: update help message close #10072
This commit is contained in:
6
.changeset/shy-brooms-feel.md
Normal file
6
.changeset/shy-brooms-feel.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-config": patch
|
||||
pnpm: patch
|
||||
---
|
||||
|
||||
When both `pnpm-workspace.yaml` and `.npmrc` exist, `pnpm config set --location=project` now writes to `pnpm-workspace.yaml` (matching read priority) [#10072](https://github.com/pnpm/pnpm/issues/10072).
|
||||
@@ -54,7 +54,7 @@ export function help (): string {
|
||||
shortAlias: '-g',
|
||||
},
|
||||
{
|
||||
description: 'When set to "project", the .npmrc file at the nearest package.json will be used. If no .npmrc file is present in the directory, the setting will be written to a pnpm-workspace.yaml file.',
|
||||
description: 'When set to "project", the pnpm-workspace.yaml file will be used if it exists. If only .npmrc exists, it will be used. If neither exists, a pnpm-workspace.yaml file will be created.',
|
||||
name: '--location <project|global>',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import util from 'util'
|
||||
import { types } from '@pnpm/config'
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
@@ -11,6 +9,7 @@ import kebabCase from 'lodash.kebabcase'
|
||||
import { readIniFile } from 'read-ini-file'
|
||||
import { writeIniFile } from 'write-ini-file'
|
||||
import { type ConfigCommandOptions } from './ConfigCommandOptions.js'
|
||||
import { getConfigFilePath } from './getConfigFilePath.js'
|
||||
import { isStrictlyKebabCase } from './isStrictlyKebabCase.js'
|
||||
import { settingShouldFallBackToNpm } from './settingShouldFallBackToNpm.js'
|
||||
|
||||
@@ -36,8 +35,17 @@ export async function configSet (opts: ConfigCommandOptions, key: string, valueP
|
||||
}
|
||||
throw new PnpmError('CONFIG_SET_AUTH_NON_STRING', `Cannot set ${key} to a non-string value (${JSON.stringify(value)})`)
|
||||
}
|
||||
if (opts.global === true || fs.existsSync(path.join(opts.dir, '.npmrc'))) {
|
||||
const configPath = opts.global ? path.join(opts.configDir, 'rc') : path.join(opts.dir, '.npmrc')
|
||||
|
||||
const { configPath, isWorkspaceYaml } = getConfigFilePath(opts)
|
||||
|
||||
if (isWorkspaceYaml) {
|
||||
key = camelCase(key)
|
||||
await updateWorkspaceManifest(opts.workspaceDir ?? opts.dir, {
|
||||
updatedFields: ({
|
||||
[key]: castField(value, kebabCase(key)),
|
||||
}),
|
||||
})
|
||||
} else {
|
||||
const settings = await safeReadIniFile(configPath)
|
||||
key = kebabCase(key)
|
||||
if (value == null) {
|
||||
@@ -47,14 +55,7 @@ export async function configSet (opts: ConfigCommandOptions, key: string, valueP
|
||||
settings[key] = value
|
||||
}
|
||||
await writeIniFile(configPath, settings)
|
||||
return
|
||||
}
|
||||
key = camelCase(key)
|
||||
await updateWorkspaceManifest(opts.workspaceDir ?? opts.dir, {
|
||||
updatedFields: ({
|
||||
[key]: castField(value, kebabCase(key)),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
function castField (value: unknown, key: string) {
|
||||
|
||||
42
config/plugin-commands-config/src/getConfigFilePath.ts
Normal file
42
config/plugin-commands-config/src/getConfigFilePath.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { type ConfigCommandOptions } from './ConfigCommandOptions.js'
|
||||
|
||||
interface ConfigFilePathInfo {
|
||||
configPath: string
|
||||
isWorkspaceYaml: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Priority: pnpm-workspace.yaml > .npmrc > default to pnpm-workspace.yaml
|
||||
*/
|
||||
export function getConfigFilePath (opts: Pick<ConfigCommandOptions, 'global' | 'configDir' | 'dir'>): ConfigFilePathInfo {
|
||||
if (opts.global) {
|
||||
return {
|
||||
configPath: path.join(opts.configDir, 'rc'),
|
||||
isWorkspaceYaml: false,
|
||||
}
|
||||
}
|
||||
|
||||
const workspaceYamlPath = path.join(opts.dir, 'pnpm-workspace.yaml')
|
||||
if (fs.existsSync(workspaceYamlPath)) {
|
||||
return {
|
||||
configPath: workspaceYamlPath,
|
||||
isWorkspaceYaml: true,
|
||||
}
|
||||
}
|
||||
|
||||
const npmrcPath = path.join(opts.dir, '.npmrc')
|
||||
if (fs.existsSync(npmrcPath)) {
|
||||
return {
|
||||
configPath: npmrcPath,
|
||||
isWorkspaceYaml: false,
|
||||
}
|
||||
}
|
||||
|
||||
// If neither exists, return pnpm-workspace.yaml
|
||||
return {
|
||||
configPath: workspaceYamlPath,
|
||||
isWorkspaceYaml: true,
|
||||
}
|
||||
}
|
||||
@@ -290,3 +290,48 @@ test('config set with location=project and json=true', async () => {
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('config set when both pnpm-workspace.yaml and .npmrc exist, pnpm-workspace.yaml has priority', async () => {
|
||||
const tmp = tempDir()
|
||||
const configDir = path.join(tmp, 'global-config')
|
||||
fs.mkdirSync(configDir, { recursive: true })
|
||||
fs.writeFileSync(path.join(tmp, '.npmrc'), 'store-dir=~/store')
|
||||
fs.writeFileSync(path.join(tmp, 'pnpm-workspace.yaml'), 'fetchRetries: 5')
|
||||
|
||||
await config.handler({
|
||||
dir: process.cwd(),
|
||||
cliOptions: {},
|
||||
configDir,
|
||||
location: 'project',
|
||||
rawConfig: {},
|
||||
}, ['set', 'fetch-timeout', '2000'])
|
||||
|
||||
expect(readYamlFile(path.join(tmp, 'pnpm-workspace.yaml'))).toEqual({
|
||||
fetchRetries: 5,
|
||||
fetchTimeout: 2000,
|
||||
})
|
||||
expect(readIniFileSync(path.join(tmp, '.npmrc'))).toEqual({
|
||||
'store-dir': '~/store',
|
||||
})
|
||||
})
|
||||
|
||||
test('config set when only pnpm-workspace.yaml exists, writes to it', async () => {
|
||||
const tmp = tempDir()
|
||||
const configDir = path.join(tmp, 'global-config')
|
||||
fs.mkdirSync(configDir, { recursive: true })
|
||||
fs.writeFileSync(path.join(tmp, 'pnpm-workspace.yaml'), 'fetchRetries: 5')
|
||||
|
||||
await config.handler({
|
||||
dir: process.cwd(),
|
||||
cliOptions: {},
|
||||
configDir,
|
||||
location: 'project',
|
||||
rawConfig: {},
|
||||
}, ['set', 'fetch-timeout', '3000'])
|
||||
|
||||
expect(readYamlFile(path.join(tmp, 'pnpm-workspace.yaml'))).toEqual({
|
||||
fetchRetries: 5,
|
||||
fetchTimeout: 3000,
|
||||
})
|
||||
expect(fs.existsSync(path.join(tmp, '.npmrc'))).toBeFalsy()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user