mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-12 02:57:44 -04:00
Replaces the dual `authConfig` (raw .npmrc) + `authInfos` (parsed auth) + `sslConfigs` (parsed SSL) pattern with a single structured `configByUri: Record<string, RegistryConfig>` field on Config.
### New types (`@pnpm/types`)
- **`RegistryConfig`** — per-registry config: `{ creds?: Creds, tls?: TlsConfig }`
- **`Creds`** — auth credentials: `{ authToken?, basicAuth?, tokenHelper? }`
- **`TlsConfig`** — TLS config: `{ cert?, key?, ca? }`
### Key changes
- Rewrite `createGetAuthHeaderByURI` to accept `Record<string, RegistryConfig>` instead of raw .npmrc key-value pairs
- Eliminate duplicate auth parsing between `getAuthHeadersFromConfig` and `getNetworkConfigs`
- Remove `authConfig` from the install pipeline (`StrictInstallOptions`, `HeadlessOptions`), replaced by `configByUri`
- Remove `sslConfigs` from Config — SSL fields now live in `configByUri[uri].tls`
- Remove `authConfig['registry']` mutation in `extendInstallOptions` (default registry now passed directly to `createGetAuthHeaderByURI`)
- `authConfig` remains on Config only for raw .npmrc access (config commands, error reporting, config inheritance)
### Security
- tokenHelper in project .npmrc now throws instead of being silently stripped
- tokenHelper execution uses `shell: false` to prevent shell metacharacter injection
- Basic auth uses `Buffer.from().toString('base64')` instead of `btoa()` for Unicode safety
- Dispatcher only creates custom agents when entries actually have TLS fields
87 lines
2.5 KiB
TypeScript
87 lines
2.5 KiB
TypeScript
import { jest } from '@jest/globals'
|
|
import { PnpmError } from '@pnpm/error'
|
|
|
|
const mockRunPnpmCli = jest.fn()
|
|
jest.unstable_mockModule('@pnpm/exec.pnpm-cli-runner', () => ({
|
|
runPnpmCli: mockRunPnpmCli,
|
|
}))
|
|
|
|
const { env } = await import('@pnpm/engine.runtime.commands')
|
|
|
|
beforeEach(() => {
|
|
mockRunPnpmCli.mockClear()
|
|
})
|
|
|
|
test('env use calls pnpm add with the correct arguments', async () => {
|
|
await env.handler({
|
|
bin: '/usr/local/bin',
|
|
cacheDir: '/tmp/cache',
|
|
global: true,
|
|
pnpmHomeDir: '/tmp/pnpm-home',
|
|
configByUri: {},
|
|
storeDir: '/tmp/store',
|
|
}, ['use', '18'])
|
|
|
|
expect(mockRunPnpmCli).toHaveBeenCalledWith(
|
|
['add', '--global', 'node@runtime:18', '--global-bin-dir', '/usr/local/bin', '--store-dir', '/tmp/store', '--cache-dir', '/tmp/cache'],
|
|
{ cwd: '/tmp/pnpm-home' }
|
|
)
|
|
})
|
|
|
|
test('env use passes lts specifier through unchanged', async () => {
|
|
await env.handler({
|
|
bin: '/usr/local/bin',
|
|
global: true,
|
|
pnpmHomeDir: '/tmp/pnpm-home',
|
|
configByUri: {},
|
|
storeDir: '/tmp/store',
|
|
}, ['use', 'lts'])
|
|
|
|
expect(mockRunPnpmCli).toHaveBeenCalledWith(
|
|
['add', '--global', 'node@runtime:lts', '--global-bin-dir', '/usr/local/bin', '--store-dir', '/tmp/store'],
|
|
{ cwd: '/tmp/pnpm-home' }
|
|
)
|
|
})
|
|
|
|
test('env use passes codename specifier through unchanged', async () => {
|
|
await env.handler({
|
|
bin: '/usr/local/bin',
|
|
global: true,
|
|
pnpmHomeDir: '/tmp/pnpm-home',
|
|
configByUri: {},
|
|
storeDir: '/tmp/store',
|
|
}, ['use', 'argon'])
|
|
|
|
expect(mockRunPnpmCli).toHaveBeenCalledWith(
|
|
['add', '--global', 'node@runtime:argon', '--global-bin-dir', '/usr/local/bin', '--store-dir', '/tmp/store'],
|
|
{ cwd: '/tmp/pnpm-home' }
|
|
)
|
|
})
|
|
|
|
test('fail if not run with --global', async () => {
|
|
await expect(
|
|
env.handler({
|
|
bin: '/usr/local/bin',
|
|
global: false,
|
|
pnpmHomeDir: '/tmp/pnpm-home',
|
|
configByUri: {},
|
|
}, ['use', '18'])
|
|
).rejects.toEqual(new PnpmError('NOT_IMPLEMENTED_YET', '"pnpm env use <version>" can only be used with the "--global" option currently'))
|
|
|
|
expect(mockRunPnpmCli).not.toHaveBeenCalled()
|
|
})
|
|
|
|
test('fail if there is no global bin directory', async () => {
|
|
await expect(
|
|
env.handler({
|
|
// @ts-expect-error
|
|
bin: undefined,
|
|
global: true,
|
|
pnpmHomeDir: '/tmp/pnpm-home',
|
|
configByUri: {},
|
|
}, ['use', 'lts'])
|
|
).rejects.toEqual(new PnpmError('CANNOT_MANAGE_NODE', 'Unable to manage Node.js because pnpm was not installed using the standalone installation script'))
|
|
|
|
expect(mockRunPnpmCli).not.toHaveBeenCalled()
|
|
})
|