fix: proper types of settings in local .npmrc files (#8775)

close #5075
close #8758
This commit is contained in:
Zoltan Kochan
2024-11-17 17:15:29 +01:00
committed by GitHub
parent ef7c10221c
commit 1dbc56a977
5 changed files with 30 additions and 7 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/config": patch
"pnpm": patch
---
Convert settings in local `.npmrc` files to their correct types. For instance, `child-concurrency` should be a number, not a string [#5075](https://github.com/pnpm/pnpm/issues/5075).

View File

@@ -29,6 +29,10 @@ declare module '@pnpm/npm-conf' {
export = anything
}
declare module '@pnpm/npm-conf/lib/util' {
export function parseField (types: any, field: string, value: any): unknown
}
declare module '@pnpm/npm-lifecycle' {
const anything: any
export = anything

View File

@@ -3,12 +3,22 @@ import util from 'util'
import camelcaseKeys from 'camelcase-keys'
import { envReplace } from '@pnpm/config.env-replace'
import { readIniFile } from 'read-ini-file'
import { parseField } from '@pnpm/npm-conf/lib/util'
import { types } from './types'
export type LocalConfig = Record<string, string> & { hoist?: boolean }
export async function readLocalConfig (prefix: string): Promise<LocalConfig> {
try {
const ini = await readIniFile(path.join(prefix, '.npmrc')) as Record<string, string>
for (let [key, val] of Object.entries(ini)) {
if (typeof val === 'string') {
try {
key = envReplace(key, process.env)
ini[key] = parseField(types, envReplace(val, process.env), key) as any // eslint-disable-line
} catch {}
}
}
const config = camelcaseKeys(ini) as LocalConfig
if (config.shamefullyFlatten) {
config.hoistPattern = '*'
@@ -17,13 +27,6 @@ export async function readLocalConfig (prefix: string): Promise<LocalConfig> {
if (config.hoist === false) {
config.hoistPattern = ''
}
for (const [key, val] of Object.entries(config)) {
if (typeof val === 'string') {
try {
config[envReplace(key, process.env)] = envReplace(val, process.env)
} catch {}
}
}
return config
} catch (err: unknown) {
if (util.types.isNativeError(err) && 'code' in err && err.code === 'ENOENT') return {}

View File

@@ -0,0 +1 @@
child-concurrency=10

View File

@@ -0,0 +1,9 @@
import { fixtures } from '@pnpm/test-fixtures'
import { readLocalConfig } from '@pnpm/config'
const f = fixtures(__dirname)
test('readLocalConfig parse number field', async () => {
const config = await readLocalConfig(f.find('has-number-setting'))
expect(typeof config.childConcurrency).toBe('number')
})