feat(config): support custom global bin dir (#3762)

New setting supported: `global-bin-dir`
This commit is contained in:
Kaito Udagawa
2021-09-12 04:15:41 +09:00
committed by GitHub
parent a3f6d9d897
commit 6681fdcbcb
6 changed files with 79 additions and 8 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/config": minor
---
New setting added: `global-bin-dir`. `global-bin-dir` allows to set the target directory for the bin files of globally installed packages.

View File

@@ -49,6 +49,7 @@ export const types = Object.assign({
'frozen-lockfile': Boolean,
'frozen-shrinkwrap': Boolean,
'git-checks': Boolean,
'global-bin-dir': String,
'global-dir': String,
'global-path': String,
'global-pnpmfile': String,
@@ -275,13 +276,19 @@ export default async (
: path.join(firstWithWriteAccess([npmGlobalPrefix, os.homedir()]), PNPM_GLOBAL)
pnpmConfig.dir = path.join(globalDirRoot, LAYOUT_VERSION.toString())
pnpmConfig.bin = cliOptions.dir
? (
process.platform === 'win32'
? cliOptions.dir
: path.resolve(cliOptions.dir, 'bin')
)
: globalBinDir(knownGlobalBinDirCandidates, { shouldAllowWrite: opts.globalDirShouldAllowWrite === true })
const npmConfigGlobalBinDir = npmConfig.get('global-bin-dir')
if (typeof npmConfigGlobalBinDir === 'string') {
fs.mkdirSync(npmConfigGlobalBinDir, { recursive: true })
pnpmConfig.bin = npmConfigGlobalBinDir
} else {
pnpmConfig.bin = cliOptions.dir
? (
process.platform === 'win32'
? cliOptions.dir
: path.resolve(cliOptions.dir, 'bin')
)
: globalBinDir(knownGlobalBinDirCandidates, { shouldAllowWrite: opts.globalDirShouldAllowWrite === true })
}
pnpmConfig.save = true
pnpmConfig.allowNew = true
pnpmConfig.ignoreCurrentPrefs = true

View File

@@ -0,0 +1 @@
global-bin-dir=${HOME}\.local\pnpm

View File

@@ -0,0 +1 @@
global-bin-dir=${HOME}/.local/pnpm

View File

@@ -0,0 +1,57 @@
/// <reference path="../../../typings/index.d.ts"/>
import path from 'path'
import { homedir } from 'os'
import getConfig from '@pnpm/config'
const isWindows = process.platform === 'win32'
jest.mock('@zkochan/npm-conf/lib/conf', () => {
const originalModule = jest.requireActual('@zkochan/npm-conf/lib/conf')
class MockedConf extends originalModule {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor (base: any, types: any) {
super(base, types)
const globalPrefixDirName = isWindows ? 'global-bin-dir-windows' : 'global-bin-dir'
this.prefix = this.globalPrefix = path.join(__dirname, globalPrefixDirName)
this.localPrefix = __dirname
}
get (name: string) {
if (name === 'prefix') {
return this.prefix
} else {
return super.get(name)
}
}
loadPrefix () {}
}
return MockedConf
})
test('respects global-bin-dir in npmrc', async () => {
const { config } = await getConfig({
cliOptions: {
global: true,
},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
expect(config.bin).toBe(path.join(homedir(), '.local', 'pnpm'))
})
test('respects global-bin-dir rather than dir', async () => {
const { config } = await getConfig({
cliOptions: {
global: true,
dir: __dirname,
},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
expect(config.bin).toBe(path.join(homedir(), '.local', 'pnpm'))
})

View File

@@ -41,7 +41,7 @@ export async function handler (
},
params: string[]
) {
const prefix = path.join(os.tmpdir(), `dlx-${process.pid.toString()}`)
const prefix = path.join(fs.realpathSync(os.tmpdir()), `dlx-${process.pid.toString()}`)
const bins = process.platform === 'win32'
? prefix
: path.join(prefix, 'bin')