mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 07:38:12 -05:00
fix: proper types of settings in local .npmrc files (#8775)
close #5075 close #8758
This commit is contained in:
6
.changeset/short-knives-raise.md
Normal file
6
.changeset/short-knives-raise.md
Normal 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).
|
||||
4
__typings__/local.d.ts
vendored
4
__typings__/local.d.ts
vendored
@@ -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
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
1
config/config/test/fixtures/has-number-setting/.npmrc
vendored
Normal file
1
config/config/test/fixtures/has-number-setting/.npmrc
vendored
Normal file
@@ -0,0 +1 @@
|
||||
child-concurrency=10
|
||||
9
config/config/test/readLocalConfig.test.ts
Normal file
9
config/config/test/readLocalConfig.test.ts
Normal 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')
|
||||
})
|
||||
Reference in New Issue
Block a user