mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-11 02:29:48 -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
62 lines
2.0 KiB
TypeScript
62 lines
2.0 KiB
TypeScript
import path from 'node:path'
|
|
|
|
import { resolveConfigDeps } from '@pnpm/installing.env-installer'
|
|
import { readEnvLockfile } from '@pnpm/lockfile.fs'
|
|
import { prepareEmpty } from '@pnpm/prepare'
|
|
import { getIntegrity, REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
|
|
import { createTempStore } from '@pnpm/testing.temp-store'
|
|
import { readYamlFileSync } from 'read-yaml-file'
|
|
|
|
const registry = `http://localhost:${REGISTRY_MOCK_PORT}/`
|
|
|
|
test('configuration dependency is resolved', async () => {
|
|
prepareEmpty()
|
|
const { storeController, storeDir } = createTempStore()
|
|
|
|
await resolveConfigDeps(['@pnpm.e2e/foo@100.0.0'], {
|
|
registries: {
|
|
default: registry,
|
|
},
|
|
rootDir: process.cwd(),
|
|
cacheDir: path.resolve('cache'),
|
|
store: storeController,
|
|
storeDir,
|
|
})
|
|
|
|
// Workspace manifest should have a clean specifier (no integrity)
|
|
const workspaceManifest = readYamlFileSync<{ configDependencies: Record<string, string> }>('pnpm-workspace.yaml')
|
|
expect(workspaceManifest.configDependencies).toStrictEqual({
|
|
'@pnpm.e2e/foo': '100.0.0',
|
|
})
|
|
|
|
// Env lockfile should contain the resolved dependency with integrity
|
|
const envLockfile = await readEnvLockfile(process.cwd())
|
|
expect(envLockfile).not.toBeNull()
|
|
expect(envLockfile!.importers['.'].configDependencies['@pnpm.e2e/foo']).toStrictEqual({
|
|
specifier: '100.0.0',
|
|
version: '100.0.0',
|
|
})
|
|
expect(envLockfile!.packages['@pnpm.e2e/foo@100.0.0']).toStrictEqual({
|
|
resolution: {
|
|
integrity: getIntegrity('@pnpm.e2e/foo', '100.0.0'),
|
|
},
|
|
})
|
|
expect(envLockfile!.snapshots['@pnpm.e2e/foo@100.0.0']).toStrictEqual({})
|
|
})
|
|
|
|
test('fails with frozenLockfile', async () => {
|
|
prepareEmpty()
|
|
const { storeController, storeDir } = createTempStore()
|
|
|
|
await expect(resolveConfigDeps(['@pnpm.e2e/foo@100.0.0'], {
|
|
registries: {
|
|
default: registry,
|
|
},
|
|
rootDir: process.cwd(),
|
|
cacheDir: path.resolve('cache'),
|
|
store: storeController,
|
|
storeDir,
|
|
frozenLockfile: true,
|
|
})).rejects.toThrow('Cannot resolve configDependencies with "frozen-lockfile"')
|
|
})
|