mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-27 18:46:18 -04:00
fix: explicitly tell npm the config file path (#10154)
* fix: explicitly tell npm the config file path * fix: `managingAuthSettings` * feat: other `npm` call-sites * docs: changeset * fix: make optional again * feat: remove the change from `publish` * fix: eslint * refactor: just one is sufficient
This commit is contained in:
7
.changeset/pretty-readers-know.md
Normal file
7
.changeset/pretty-readers-know.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@pnpm/run-npm": minor
|
||||
"@pnpm/plugin-commands-config": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Explicitly tell `npm` the path to the global `rc` config file.
|
||||
@@ -1,3 +1,4 @@
|
||||
import path from 'path'
|
||||
import kebabCase from 'lodash.kebabcase'
|
||||
import { types } from '@pnpm/config'
|
||||
import { isCamelCase, isStrictlyKebabCase } from '@pnpm/naming-cases'
|
||||
@@ -13,7 +14,10 @@ export function configGet (opts: ConfigCommandOptions, key: string): { output: s
|
||||
// Exclude scoped keys from npm fallback because they are pnpm-native config
|
||||
// that can be read directly from rawConfig (e.g., '@scope:registry')
|
||||
if (opts.global && settingShouldFallBackToNpm(key) && !isScopedKey) {
|
||||
const { status: exitCode } = runNpm(opts.npmPath, ['config', 'get', key])
|
||||
const { status: exitCode } = runNpm(opts.npmPath, ['config', 'get', key], {
|
||||
location: 'user',
|
||||
userConfigPath: path.join(opts.configDir, 'rc'),
|
||||
})
|
||||
return { output: '', exitCode: exitCode ?? 0 }
|
||||
}
|
||||
const configResult = getRcConfig(opts.rawConfig, key, isScopedKey) ?? getConfigByPropertyPath(opts.rawConfig, key)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { types } from '@pnpm/config'
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
import { isCamelCase, isStrictlyKebabCase } from '@pnpm/naming-cases'
|
||||
import { parsePropertyPath } from '@pnpm/object.property-path'
|
||||
import { runNpm } from '@pnpm/run-npm'
|
||||
import { type RunNPMOptions, runNpm } from '@pnpm/run-npm'
|
||||
import { updateWorkspaceManifest } from '@pnpm/workspace.manifest-writer'
|
||||
import camelCase from 'camelcase'
|
||||
import kebabCase from 'lodash.kebabcase'
|
||||
@@ -27,13 +27,18 @@ export async function configSet (opts: ConfigCommandOptions, key: string, valueP
|
||||
|
||||
if (shouldFallbackToNpm) {
|
||||
if (opts.global) {
|
||||
const configPath = path.join(opts.configDir, 'rc')
|
||||
const runNpmOpts: RunNPMOptions = {
|
||||
location: 'user',
|
||||
userConfigPath: configPath,
|
||||
}
|
||||
const _runNpm = runNpm.bind(null, opts.npmPath)
|
||||
if (value == null) {
|
||||
_runNpm(['config', 'delete', key])
|
||||
_runNpm(['config', 'delete', key], runNpmOpts)
|
||||
return
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
_runNpm(['config', 'set', `${key}=${value}`])
|
||||
_runNpm(['config', 'set', `${key}=${value}`], runNpmOpts)
|
||||
return
|
||||
}
|
||||
throw new PnpmError('CONFIG_SET_AUTH_NON_STRING', `Cannot set ${key} to a non-string value (${JSON.stringify(value)})`)
|
||||
|
||||
@@ -27,11 +27,17 @@ describe.each(
|
||||
}
|
||||
it(`should set ${key}`, async () => {
|
||||
await config.handler(configOpts, ['set', `${key}=123`])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'set', `${key}=123`])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'set', `${key}=123`], expect.objectContaining({
|
||||
location: 'user',
|
||||
userConfigPath: expect.any(String),
|
||||
}))
|
||||
})
|
||||
it(`should delete ${key}`, async () => {
|
||||
await config.handler(configOpts, ['delete', key])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'delete', key])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'delete', key], expect.objectContaining({
|
||||
location: 'user',
|
||||
userConfigPath: expect.any(String),
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -45,11 +51,17 @@ describe.each(
|
||||
}
|
||||
it(`should set ${key}`, async () => {
|
||||
await config.handler(configOpts, ['set', key, '"123"'])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'set', `${key}=123`])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'set', `${key}=123`], expect.objectContaining({
|
||||
location: 'user',
|
||||
userConfigPath: expect.any(String),
|
||||
}))
|
||||
})
|
||||
it(`should delete ${key}`, async () => {
|
||||
await config.handler(configOpts, ['delete', key])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'delete', key])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'delete', key], expect.objectContaining({
|
||||
location: 'user',
|
||||
userConfigPath: expect.any(String),
|
||||
}))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -93,10 +105,16 @@ describe.each(
|
||||
}
|
||||
it('should set _auth', async () => {
|
||||
await config.handler(configOpts, ['set', propertyPath, '123'])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'set', '_auth=123'])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'set', '_auth=123'], expect.objectContaining({
|
||||
location: 'user',
|
||||
userConfigPath: expect.any(String),
|
||||
}))
|
||||
})
|
||||
it('should delete _auth', async () => {
|
||||
await config.handler(configOpts, ['delete', propertyPath])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'delete', '_auth'])
|
||||
expect(runNpm).toHaveBeenCalledWith(undefined, ['config', 'delete', '_auth'], expect.objectContaining({
|
||||
location: 'user',
|
||||
userConfigPath: expect.any(String),
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -3,9 +3,13 @@ import path from 'path'
|
||||
import spawn from 'cross-spawn'
|
||||
import PATH from 'path-name'
|
||||
|
||||
export type NPMLocation = 'global' | 'user' | 'project'
|
||||
|
||||
export interface RunNPMOptions {
|
||||
cwd?: string
|
||||
env?: Record<string, string>
|
||||
location?: NPMLocation
|
||||
userConfigPath?: string
|
||||
}
|
||||
|
||||
export function runNpm (npmPath: string | undefined, args: string[], options?: RunNPMOptions): childProcess.SpawnSyncReturns<Buffer> {
|
||||
@@ -15,6 +19,8 @@ export function runNpm (npmPath: string | undefined, args: string[], options?: R
|
||||
stdio: 'inherit',
|
||||
userAgent: undefined,
|
||||
env: { ...options?.env, COREPACK_ENABLE_STRICT: '0' },
|
||||
location: options?.location,
|
||||
userConfigPath: options?.userConfigPath,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,8 +29,10 @@ export function runScriptSync (
|
||||
args: string[],
|
||||
opts: {
|
||||
cwd: string
|
||||
location?: NPMLocation
|
||||
stdio: childProcess.StdioOptions
|
||||
userAgent?: string
|
||||
userConfigPath?: string
|
||||
env: Record<string, string>
|
||||
}
|
||||
): childProcess.SpawnSyncReturns<Buffer> {
|
||||
@@ -43,7 +51,9 @@ export function runScriptSync (
|
||||
function createEnv (
|
||||
opts: {
|
||||
cwd: string
|
||||
location?: NPMLocation
|
||||
userAgent?: string
|
||||
userConfigPath?: string
|
||||
}
|
||||
): NodeJS.ProcessEnv {
|
||||
const env = { ...process.env }
|
||||
@@ -58,5 +68,13 @@ function createEnv (
|
||||
env.npm_config_user_agent = opts.userAgent
|
||||
}
|
||||
|
||||
if (opts.location) {
|
||||
env.npm_config_location = opts.location
|
||||
}
|
||||
|
||||
if (opts.userConfigPath) {
|
||||
env.npm_config_userconfig = opts.userConfigPath
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import path from 'path'
|
||||
import { type SpawnSyncReturns } from 'child_process'
|
||||
import { packageManager } from '@pnpm/cli-meta'
|
||||
import { getConfig, types as allTypes } from '@pnpm/config'
|
||||
@@ -14,5 +15,8 @@ export async function runNpm (args: string[]): Promise<SpawnSyncReturns<Buffer>>
|
||||
], allTypes),
|
||||
},
|
||||
})
|
||||
return _runNpm(config.npmPath, args)
|
||||
return _runNpm(config.npmPath, args, {
|
||||
// This code is only used in `passThruToNpm`, so it is safe to specify `userConfigPath` here.
|
||||
userConfigPath: path.join(config.configDir, 'rc'),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user