feat(dlx): read auth from local .npmrc (#8207)

close #7996
This commit is contained in:
Khải
2024-06-25 22:51:43 +07:00
committed by GitHub
parent 9b5b869322
commit 1b03682903
11 changed files with 341 additions and 160 deletions

View File

@@ -0,0 +1,7 @@
---
"@pnpm/config": minor
"@pnpm/plugin-commands-script-runners": minor
"pnpm": patch
---
Read authentication information from .npmrc in the current directory when running `dlx` [#7996](https://github.com/pnpm/pnpm/issues/7996).

View File

@@ -10,6 +10,7 @@ export async function getConfig (
rcOptionsTypes: Record<string, unknown>
workspaceDir: string | undefined
checkUnknownSetting?: boolean
ignoreNonAuthSettingsFromLocal?: boolean
}
): Promise<Config> {
const { config, warnings } = await _getConfig({
@@ -19,6 +20,7 @@ export async function getConfig (
rcOptionsTypes: opts.rcOptionsTypes,
workspaceDir: opts.workspaceDir,
checkUnknownSetting: opts.checkUnknownSetting,
ignoreNonAuthSettingsFromLocal: opts.ignoreNonAuthSettingsFromLocal,
})
config.cliOptions = cliOptions

View File

@@ -0,0 +1,52 @@
import { inheritAuthConfig } from './auth'
import { type InheritableConfig } from './inheritPickedConfig'
test('inheritAuthConfig copies only auth keys from source to target', () => {
const target: InheritableConfig = {
bin: 'foo',
cacheDir: '/path/to/cache/dir',
registry: 'https://npmjs.com/registry/',
rawConfig: {
'cache-dir': '/path/to/cache/dir',
registry: 'https://npmjs.com/registry/',
},
rawLocalConfig: {
bin: 'foo',
registry: 'https://npmjs.com/registry/',
},
}
inheritAuthConfig(target, {
bin: 'bar',
cacheDir: '/path/to/another/cache/dir',
storeDir: '/path/to/custom/store/dir',
registry: 'https://example.com/local-registry/',
rawConfig: {
registry: 'https://example.com/global-registry/',
'//example.com/global-registry/:_auth': 'MY_SECRET_GLOBAL_AUTH',
},
rawLocalConfig: {
bin: 'bar',
'cache-dir': '/path/to/another/cache/dir',
'store-dir': '/path/to/custom/store/dir',
registry: 'https://example.com/local-registry/',
'//example.com/local-registry/:_authToken': 'MY_SECRET_LOCAL_AUTH',
},
})
expect(target).toStrictEqual({
bin: 'foo',
cacheDir: '/path/to/cache/dir',
registry: 'https://example.com/local-registry/',
rawConfig: {
'cache-dir': '/path/to/cache/dir',
registry: 'https://example.com/global-registry/',
'//example.com/global-registry/:_auth': 'MY_SECRET_GLOBAL_AUTH',
},
rawLocalConfig: {
bin: 'foo',
registry: 'https://example.com/local-registry/',
'//example.com/local-registry/:_authToken': 'MY_SECRET_LOCAL_AUTH',
},
})
})

75
config/config/src/auth.ts Normal file
View File

@@ -0,0 +1,75 @@
import { type Config } from './Config'
import { type InheritableConfig, inheritPickedConfig } from './inheritPickedConfig'
import { type types } from './types'
const RAW_AUTH_CFG_KEYS = [
'ca',
'cafile',
'cert',
'key',
'local-address',
'git-shallow-hosts',
'https-proxy',
'proxy',
'no-proxy',
'registry',
'strict-ssl',
] satisfies Array<keyof typeof types>
const RAW_AUTH_CFG_KEY_SUFFIXES = [
':cafile',
':certfile',
':keyfile',
':registry',
':tokenHelper',
':_auth',
':_authToken',
]
const AUTH_CFG_KEYS = [
'ca',
'cert',
'key',
'localAddress',
'gitShallowHosts',
'httpsProxy',
'httpProxy',
'noProxy',
'registry',
'registries',
'strictSsl',
] satisfies Array<keyof Config>
function isRawAuthCfgKey (rawCfgKey: string): boolean {
if ((RAW_AUTH_CFG_KEYS as string[]).includes(rawCfgKey)) return true
if (RAW_AUTH_CFG_KEY_SUFFIXES.some(suffix => rawCfgKey.endsWith(suffix))) return true
return false
}
function isAuthCfgKey (cfgKey: keyof Config): cfgKey is typeof AUTH_CFG_KEYS[number] {
return (AUTH_CFG_KEYS as Array<keyof Config>).includes(cfgKey)
}
function pickRawAuthConfig<RawLocalCfg extends Record<string, unknown>> (rawLocalCfg: RawLocalCfg): Partial<RawLocalCfg> {
const result: Partial<RawLocalCfg> = {}
for (const key in rawLocalCfg) {
if (isRawAuthCfgKey(key)) {
result[key] = rawLocalCfg[key]
}
}
return result
}
function pickAuthConfig (localCfg: Partial<Config>): Partial<Config> {
const result: Record<string, unknown> = {}
for (const key in localCfg) {
if (isAuthCfgKey(key as keyof Config)) {
result[key] = localCfg[key as keyof Config]
}
}
return result as Partial<Config>
}
export function inheritAuthConfig (targetCfg: InheritableConfig, authSrcCfg: InheritableConfig): void {
inheritPickedConfig(targetCfg, authSrcCfg, pickAuthConfig, pickRawAuthConfig)
}

View File

@@ -1,9 +1,10 @@
import path from 'path'
import fs from 'fs'
import os from 'os'
import { LAYOUT_VERSION } from '@pnpm/constants'
import { PnpmError } from '@pnpm/error'
import loadNpmConf from '@pnpm/npm-conf'
import npmTypes from '@pnpm/npm-conf/lib/types'
import type npmTypes from '@pnpm/npm-conf/lib/types'
import { requireHooks } from '@pnpm/pnpmfile'
import { safeReadProjectManifestOnly } from '@pnpm/read-project-manifest'
import { getCurrentBranch } from '@pnpm/git-utils'
@@ -15,6 +16,7 @@ import normalizeRegistryUrl from 'normalize-registry-url'
import realpathMissing from 'realpath-missing'
import pathAbsolute from 'path-absolute'
import which from 'which'
import { inheritAuthConfig } from './auth'
import { checkGlobalBinDir } from './checkGlobalBinDir'
import { getNetworkConfigs } from './getNetworkConfigs'
import { getCacheDir, getConfigDir, getDataDir, getStateDir } from './dirs'
@@ -26,6 +28,9 @@ import {
import { getWorkspaceConcurrency } from './concurrency'
import { readWorkspaceManifest } from '@pnpm/workspace.read-manifest'
import { types } from './types'
export { types }
export { getOptionsFromRootManifest, type OptionsFromRootManifest } from './getOptionsFromRootManifest'
export * from './readLocalConfig'
@@ -41,138 +46,40 @@ type KebabCaseConfig = {
const npmDefaults = loadNpmConf.defaults
export const types = Object.assign({
'auto-install-peers': Boolean,
bail: Boolean,
'cache-dir': String,
'child-concurrency': Number,
'merge-git-branch-lockfiles': Boolean,
'merge-git-branch-lockfiles-branch-pattern': Array,
color: ['always', 'auto', 'never'],
'config-dir': String,
'deploy-all-files': Boolean,
'dedupe-peer-dependents': Boolean,
'dedupe-direct-deps': Boolean,
'dedupe-injected-deps': Boolean,
dev: [null, true],
dir: String,
'disallow-workspace-cycles': Boolean,
'enable-modules-dir': Boolean,
'enable-pre-post-scripts': Boolean,
'exclude-links-from-lockfile': Boolean,
'extend-node-path': Boolean,
'fetch-timeout': Number,
'fetching-concurrency': Number,
filter: [String, Array],
'filter-prod': [String, Array],
'frozen-lockfile': Boolean,
'git-checks': Boolean,
'git-shallow-hosts': Array,
'global-bin-dir': String,
'global-dir': String,
'global-path': String,
'global-pnpmfile': String,
'git-branch-lockfile': Boolean,
hoist: Boolean,
'hoist-pattern': Array,
'hoist-workspace-packages': Boolean,
'ignore-compatibility-db': Boolean,
'ignore-dep-scripts': Boolean,
'ignore-pnpmfile': Boolean,
'ignore-workspace': Boolean,
'ignore-workspace-cycles': Boolean,
'ignore-workspace-root-check': Boolean,
'include-workspace-root': Boolean,
'legacy-dir-filtering': Boolean,
'link-workspace-packages': [Boolean, 'deep'],
lockfile: Boolean,
'lockfile-dir': String,
'lockfile-directory': String, // TODO: deprecate
'lockfile-include-tarball-url': Boolean,
'lockfile-only': Boolean,
loglevel: ['silent', 'error', 'warn', 'info', 'debug'],
maxsockets: Number,
'modules-cache-max-age': Number,
'dlx-cache-max-age': Number,
'modules-dir': String,
'network-concurrency': Number,
'node-linker': ['pnp', 'isolated', 'hoisted'],
noproxy: String,
'npm-path': String,
offline: Boolean,
'only-built-dependencies': [String],
'pack-gzip-level': Number,
'package-import-method': ['auto', 'hardlink', 'clone', 'copy'],
'patches-dir': String,
pnpmfile: String,
'package-manager-strict': Boolean,
'package-manager-strict-version': Boolean,
'prefer-frozen-lockfile': Boolean,
'prefer-offline': Boolean,
'prefer-symlinked-executables': Boolean,
'prefer-workspace-packages': Boolean,
production: [null, true],
'public-hoist-pattern': Array,
'publish-branch': String,
'recursive-install': Boolean,
reporter: String,
'resolution-mode': ['highest', 'time-based', 'lowest-direct'],
'resolve-peers-from-workspace-root': Boolean,
'aggregate-output': Boolean,
'reporter-hide-prefix': Boolean,
'save-peer': Boolean,
'save-workspace-protocol': Boolean,
'script-shell': String,
'shamefully-flatten': Boolean,
'shamefully-hoist': Boolean,
'shared-workspace-lockfile': Boolean,
'shell-emulator': Boolean,
'side-effects-cache': Boolean,
'side-effects-cache-readonly': Boolean,
symlink: Boolean,
sort: Boolean,
'state-dir': String,
'store-dir': String,
stream: Boolean,
'strict-store-pkg-content-check': Boolean,
'strict-peer-dependencies': Boolean,
'use-beta-cli': Boolean,
'use-node-version': String,
'use-running-store-server': Boolean,
'use-store-server': Boolean,
'use-stderr': Boolean,
'verify-store-integrity': Boolean,
'virtual-store-dir': String,
'virtual-store-dir-max-length': Number,
'peers-suffix-max-length': Number,
'workspace-concurrency': Number,
'workspace-packages': [String, Array],
'workspace-root': Boolean,
'test-pattern': [String, Array],
'changed-files-ignore-pattern': [String, Array],
'embed-readme': Boolean,
'update-notifier': Boolean,
'registry-supports-time-field': Boolean,
'fail-if-no-match': Boolean,
}, npmTypes.types)
export type CliOptions = Record<string, unknown> & { dir?: string, json?: boolean }
export async function getConfig (
opts: {
globalDirShouldAllowWrite?: boolean
cliOptions: CliOptions
packageManager: {
name: string
version: string
}
rcOptionsTypes?: Record<string, unknown>
workspaceDir?: string | undefined
checkUnknownSetting?: boolean
env?: Record<string, string | undefined>
export async function getConfig (opts: {
globalDirShouldAllowWrite?: boolean
cliOptions: CliOptions
packageManager: {
name: string
version: string
}
): Promise<{ config: Config, warnings: string[] }> {
rcOptionsTypes?: Record<string, unknown>
workspaceDir?: string | undefined
checkUnknownSetting?: boolean
env?: Record<string, string | undefined>
ignoreNonAuthSettingsFromLocal?: boolean
}): Promise<{ config: Config, warnings: string[] }> {
if (opts.ignoreNonAuthSettingsFromLocal) {
const { ignoreNonAuthSettingsFromLocal: _, ...authOpts } = opts
const globalCfgOpts: typeof authOpts = {
...authOpts,
cliOptions: {
...authOpts.cliOptions,
dir: os.homedir(),
},
}
const [final, authSrc] = await Promise.all([getConfig(globalCfgOpts), getConfig(authOpts)])
inheritAuthConfig(final.config, authSrc.config)
if (final.warnings) {
final.warnings.push(...authSrc.warnings)
} else {
final.warnings = authSrc.warnings
}
return final
}
const env = opts.env ?? process.env
const packageManager = opts.packageManager ?? { name: 'pnpm', version: 'undefined' }
const cliOptions = opts.cliOptions ?? {}

View File

@@ -0,0 +1,17 @@
import { type Config } from './Config'
export type InheritableConfig = Partial<Config> & Pick<Config, 'rawConfig' | 'rawLocalConfig'>
export type PickConfig = (cfg: Partial<Config>) => Partial<Config>
export type PickRawConfig = (cfg: Record<string, unknown>) => Record<string, unknown>
export function inheritPickedConfig (
targetCfg: InheritableConfig,
srcCfg: InheritableConfig,
pickConfig: PickConfig,
pickRawConfig: PickRawConfig,
pickRawLocalConfig: PickRawConfig = pickRawConfig
): void {
Object.assign(targetCfg, pickConfig(srcCfg))
Object.assign(targetCfg.rawConfig, pickRawConfig(srcCfg.rawConfig))
Object.assign(targetCfg.rawLocalConfig, pickRawLocalConfig(srcCfg.rawLocalConfig))
}

116
config/config/src/types.ts Normal file
View File

@@ -0,0 +1,116 @@
import npmTypes from '@pnpm/npm-conf/lib/types'
export const types = Object.assign({
'auto-install-peers': Boolean,
bail: Boolean,
'cache-dir': String,
'child-concurrency': Number,
'merge-git-branch-lockfiles': Boolean,
'merge-git-branch-lockfiles-branch-pattern': Array,
color: ['always', 'auto', 'never'],
'config-dir': String,
'deploy-all-files': Boolean,
'dedupe-peer-dependents': Boolean,
'dedupe-direct-deps': Boolean,
'dedupe-injected-deps': Boolean,
dev: [null, true],
dir: String,
'disallow-workspace-cycles': Boolean,
'enable-modules-dir': Boolean,
'enable-pre-post-scripts': Boolean,
'exclude-links-from-lockfile': Boolean,
'extend-node-path': Boolean,
'fetch-timeout': Number,
'fetching-concurrency': Number,
filter: [String, Array],
'filter-prod': [String, Array],
'frozen-lockfile': Boolean,
'git-checks': Boolean,
'git-shallow-hosts': Array,
'global-bin-dir': String,
'global-dir': String,
'global-path': String,
'global-pnpmfile': String,
'git-branch-lockfile': Boolean,
hoist: Boolean,
'hoist-pattern': Array,
'hoist-workspace-packages': Boolean,
'ignore-compatibility-db': Boolean,
'ignore-dep-scripts': Boolean,
'ignore-pnpmfile': Boolean,
'ignore-workspace': Boolean,
'ignore-workspace-cycles': Boolean,
'ignore-workspace-root-check': Boolean,
'include-workspace-root': Boolean,
'legacy-dir-filtering': Boolean,
'link-workspace-packages': [Boolean, 'deep'],
lockfile: Boolean,
'lockfile-dir': String,
'lockfile-directory': String, // TODO: deprecate
'lockfile-include-tarball-url': Boolean,
'lockfile-only': Boolean,
loglevel: ['silent', 'error', 'warn', 'info', 'debug'],
maxsockets: Number,
'modules-cache-max-age': Number,
'dlx-cache-max-age': Number,
'modules-dir': String,
'network-concurrency': Number,
'node-linker': ['pnp', 'isolated', 'hoisted'],
noproxy: String,
'npm-path': String,
offline: Boolean,
'only-built-dependencies': [String],
'pack-gzip-level': Number,
'package-import-method': ['auto', 'hardlink', 'clone', 'copy'],
'patches-dir': String,
pnpmfile: String,
'package-manager-strict': Boolean,
'package-manager-strict-version': Boolean,
'prefer-frozen-lockfile': Boolean,
'prefer-offline': Boolean,
'prefer-symlinked-executables': Boolean,
'prefer-workspace-packages': Boolean,
production: [null, true],
'public-hoist-pattern': Array,
'publish-branch': String,
'recursive-install': Boolean,
reporter: String,
'resolution-mode': ['highest', 'time-based', 'lowest-direct'],
'resolve-peers-from-workspace-root': Boolean,
'aggregate-output': Boolean,
'reporter-hide-prefix': Boolean,
'save-peer': Boolean,
'save-workspace-protocol': Boolean,
'script-shell': String,
'shamefully-flatten': Boolean,
'shamefully-hoist': Boolean,
'shared-workspace-lockfile': Boolean,
'shell-emulator': Boolean,
'side-effects-cache': Boolean,
'side-effects-cache-readonly': Boolean,
symlink: Boolean,
sort: Boolean,
'state-dir': String,
'store-dir': String,
stream: Boolean,
'strict-store-pkg-content-check': Boolean,
'strict-peer-dependencies': Boolean,
'use-beta-cli': Boolean,
'use-node-version': String,
'use-running-store-server': Boolean,
'use-store-server': Boolean,
'use-stderr': Boolean,
'verify-store-integrity': Boolean,
'virtual-store-dir': String,
'virtual-store-dir-max-length': Number,
'peers-suffix-max-length': Number,
'workspace-concurrency': Number,
'workspace-packages': [String, Array],
'workspace-root': Boolean,
'test-pattern': [String, Array],
'changed-files-ignore-pattern': [String, Array],
'embed-readme': Boolean,
'update-notifier': Boolean,
'registry-supports-time-field': Boolean,
'fail-if-no-match': Boolean,
}, npmTypes.types)

View File

@@ -101,6 +101,7 @@
"jhcg",
"jnbpamcxayl",
"kevva",
"keyfile",
"killcb",
"kochan",
"koorchik",

28
pnpm-lock.yaml generated
View File

@@ -6755,7 +6755,6 @@ packages:
'@babel/plugin-proposal-dynamic-import@7.18.6':
resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==}
engines: {node: '>=6.9.0'}
deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-dynamic-import instead.
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -7354,7 +7353,6 @@ packages:
'@humanwhocodes/config-array@0.11.14':
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
engines: {node: '>=10.10.0'}
deprecated: Use @eslint/config-array instead
'@humanwhocodes/module-importer@1.0.1':
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
@@ -7362,7 +7360,6 @@ packages:
'@humanwhocodes/object-schema@2.0.3':
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
deprecated: Use @eslint/object-schema instead
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
@@ -8398,7 +8395,6 @@ packages:
are-we-there-yet@1.1.7:
resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==}
deprecated: This package is no longer supported.
arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
@@ -9374,7 +9370,6 @@ packages:
eslint-config-standard-with-typescript@39.1.1:
resolution: {integrity: sha512-t6B5Ep8E4I18uuoYeYxINyqcXb2UbC0SOOTxRtBSt2JUs+EzeXbfe2oaiPs71AIdnoWhXDO2fYOHz8df3kV84A==}
deprecated: Please use eslint-config-love, instead.
peerDependencies:
'@typescript-eslint/eslint-plugin': ^6.4.0
eslint: ^8.0.1
@@ -9800,7 +9795,6 @@ packages:
gauge@2.7.4:
resolution: {integrity: sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==}
deprecated: This package is no longer supported.
gensequence@6.0.0:
resolution: {integrity: sha512-8WwuywE9pokJRAcg2QFR/plk3cVPebSUqRPzpGQh3WQ0wIiHAw+HyOQj5IuHyUTQBHpBKFoB2JUMu9zT3vJ16Q==}
@@ -9888,16 +9882,13 @@ packages:
glob@6.0.4:
resolution: {integrity: sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==}
deprecated: Glob versions prior to v9 are no longer supported
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
deprecated: Glob versions prior to v9 are no longer supported
global-dirs@0.1.1:
resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==}
@@ -9969,7 +9960,6 @@ packages:
har-validator@5.1.5:
resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==}
engines: {node: '>=6'}
deprecated: this library is no longer supported
hard-rejection@2.1.0:
resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
@@ -10150,7 +10140,6 @@ packages:
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
@@ -11328,7 +11317,6 @@ packages:
osenv@0.1.5:
resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==}
deprecated: This package is no longer supported.
outdent@0.5.0:
resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
@@ -11852,12 +11840,10 @@ packages:
request@2.88.0:
resolution: {integrity: sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==}
engines: {node: '>= 4'}
deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
request@2.88.2:
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
engines: {node: '>= 6'}
deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
@@ -11940,24 +11926,20 @@ packages:
right-pad@1.0.1:
resolution: {integrity: sha512-bYBjgxmkvTAfgIYy328fmkwhp39v8lwVgWhhrzxPV3yHtcSqyYKe9/XOhvW48UFjATg3VuJbpsp5822ACNvkmw==}
engines: {node: '>= 0.10'}
deprecated: Please use String.prototype.padEnd() over this package.
rimraf-then@1.0.1:
resolution: {integrity: sha512-qTVCDUsBDO74PHen/pEMTHeQXxrCSeTcFhqjy86mkRH5nuGZpEv41ZgGunxmjbl29kvrKJGrgVFThoqXeRORfQ==}
rimraf@2.4.5:
resolution: {integrity: sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
rimraf@2.7.1:
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
root-link-target@3.1.0:
@@ -12745,7 +12727,6 @@ packages:
uuid@3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
hasBin: true
uuid@9.0.1:
@@ -20718,11 +20699,4 @@ snapshots:
zwitch@1.0.5: {}
time:
'@pnpm/hosted-git-info@1.0.0': '2024-02-05T14:40:06.830Z'
'@pnpm/node-fetch@1.0.0': '2023-04-19T11:13:43.487Z'
'@pnpm/ramda@0.28.1': '2022-08-03T13:56:59.597Z'
'@pnpm/which@3.0.1': '2023-05-14T22:08:27.551Z'
'@types/byline@4.2.36': '2023-11-07T00:13:37.410Z'
'@types/table@6.0.0': '2020-09-17T17:56:44.787Z'
'@zkochan/js-yaml@0.0.7': '2024-03-08T10:21:15.389Z'
time: {}

View File

@@ -21,7 +21,6 @@ import { formatUnknownOptionsError } from './formatError'
import { parseCliArgs } from './parseCliArgs'
import { initReporter, type ReporterType } from './reporter'
import { isCI } from 'ci-info'
import os from 'os'
import path from 'path'
import isEmpty from 'ramda/src/isEmpty'
import stripAnsi from 'strip-ansi'
@@ -91,12 +90,13 @@ export async function main (inputArgv: string[]): Promise<void> {
// we don't need the write permission to it. Related issue: #2700
const globalDirShouldAllowWrite = cmd !== 'root'
const isDlxCommand = cmd === 'dlx'
config = await getConfig(isDlxCommand ? { ...cliOptions, dir: os.homedir() } : cliOptions, {
config = await getConfig(cliOptions, {
excludeReporter: false,
globalDirShouldAllowWrite,
rcOptionsTypes,
workspaceDir,
checkUnknownSetting: false,
ignoreNonAuthSettingsFromLocal: isDlxCommand,
}) as typeof config
if (isDlxCommand) {
config.useStderr = true

View File

@@ -4,6 +4,7 @@ import PATH_NAME from 'path-name'
import { createBase32Hash } from '@pnpm/crypto.base32-hash'
import { prepare, prepareEmpty } from '@pnpm/prepare'
import { readModulesManifest } from '@pnpm/modules-yaml'
import { addUser, REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
import { execPnpm, execPnpmSync } from './utils'
test('silent dlx prints the output of the child process only', async () => {
@@ -197,7 +198,7 @@ test('dlx creates cache and store prune cleans cache', async () => {
).toStrictEqual([])
})
test('dlx should ignore .npmrc in the current directory', async () => {
test('dlx should ignore non-auth info from .npmrc in the current directory', async () => {
prepare({})
fs.writeFileSync('.npmrc', 'hoist-pattern=', 'utf8')
@@ -210,3 +211,32 @@ test('dlx should ignore .npmrc in the current directory', async () => {
const modulesManifest = await readModulesManifest(path.join(cacheDir, 'dlx', createBase32Hash('shx'), 'pkg/node_modules'))
expect(modulesManifest?.hoistPattern).toStrictEqual(['*'])
})
test('dlx read registry from .npmrc in the current directory', async () => {
prepareEmpty()
const data = await addUser({
email: 'foo@bar.com',
password: 'bar',
username: 'foo',
})
fs.writeFileSync('.npmrc', [
`registry=http://localhost:${REGISTRY_MOCK_PORT}/`,
`//localhost:${REGISTRY_MOCK_PORT}/:_authToken=${data.token}`,
].join('\n'))
const execResult = execPnpmSync([
`--config.store-dir=${path.resolve('store')}`,
`--config.cache-dir=${path.resolve('cache')}`,
'--package=@pnpm.e2e/needs-auth',
'dlx',
'hello-from-needs-auth',
], {
env: {},
stdio: [null, 'pipe', 'inherit'],
})
expect(execResult.stdout.toString().trim()).toBe('hello from @pnpm.e2e/needs-auth')
expect(execResult.status).toBe(0)
})