Skip to content

Commit 27ad872

Browse files
committed
fix: ignore project .npmrc for background update check
1 parent ddf1c28 commit 27ad872

3 files changed

Lines changed: 28 additions & 11 deletions

File tree

packages/nuxt-cli/src/utils/registry.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,12 @@ export function getRegistryFromContent(content: string, scope: string | null): s
4444
}
4545
}
4646

47-
function getNpmrcPaths(cwd: string): string[] {
48-
return [join(cwd, '.npmrc'), join(homedir(), '.npmrc')]
47+
/**
48+
* `.npmrc` files to consult, most specific first. Without a `cwd` only the user's
49+
* own file is read, for requests a project should not be able to redirect.
50+
*/
51+
function getNpmrcPaths(cwd: string | undefined): string[] {
52+
return cwd ? [join(cwd, '.npmrc'), join(homedir(), '.npmrc')] : [join(homedir(), '.npmrc')]
4953
}
5054

5155
async function getRegistryFromFile(paths: string[], scope: string | null) {
@@ -72,7 +76,7 @@ async function getRegistryFromFile(paths: string[], scope: string | null) {
7276
return null
7377
}
7478

75-
async function getRegistry(scope: string | null, cwd: string): Promise<string> {
79+
async function getRegistry(scope: string | null, cwd: string | undefined): Promise<string> {
7680
const registry = process.env.COREPACK_NPM_REGISTRY
7781
|| await getRegistryFromFile(getNpmrcPaths(cwd), scope)
7882
|| PUBLIC_REGISTRY
@@ -128,7 +132,7 @@ function readCredentials(config: Record<string, string | undefined>, registry: s
128132
}
129133
}
130134

131-
async function getCredentials(registry: RegistryMeta['registry'], cwd: string): Promise<Pick<RegistryMeta, 'authToken' | 'authorization'>> {
135+
async function getCredentials(registry: RegistryMeta['registry'], cwd: string | undefined): Promise<Pick<RegistryMeta, 'authToken' | 'authorization'>> {
132136
for (const npmrcPath of getNpmrcPaths(cwd)) {
133137
let fd: FileHandle | undefined
134138
try {
@@ -152,11 +156,19 @@ async function getCredentials(registry: RegistryMeta['registry'], cwd: string):
152156
return { authToken: null, authorization: null }
153157
}
154158

155-
export async function detectNpmRegistry(scope: string | null, cwd = process.cwd()): Promise<RegistryMeta> {
156-
const registry = await getRegistry(scope, cwd)
159+
/**
160+
* Registry and credentials for `scope`, from the project's `.npmrc` in `cwd`
161+
* (defaulting to the working directory) and then the user's. Pass `null` as
162+
* `cwd` to ignore project configuration entirely: a project `.npmrc` may name any
163+
* host and, as in `npm`, reference environment variables in its credentials, so
164+
* a request the user did not ask for should not be steered by it.
165+
*/
166+
export async function detectNpmRegistry(scope: string | null, cwd: string | null = process.cwd()): Promise<RegistryMeta> {
167+
const paths = cwd ?? undefined
168+
const registry = await getRegistry(scope, paths)
157169

158170
return {
159171
registry,
160-
...await getCredentials(registry, cwd),
172+
...await getCredentials(registry, paths),
161173
}
162174
}

packages/nuxt-cli/src/utils/update-check.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ async function resolveLatestVersion(name: string): Promise<string | undefined> {
8484

8585
let latest: string | undefined
8686
try {
87-
const { registry, authorization } = await detectNpmRegistry(null)
87+
const { registry, authorization } = await detectNpmRegistry(null, null)
8888
latest = (await fetchJson<{ latest?: string }>(`${registry}/-/package/${name}/dist-tags`, {
8989
headers: authorization ? { Authorization: authorization } : undefined,
9090
timeout: FETCH_TIMEOUT,

packages/nuxt-cli/test/unit/utils/update.spec.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const rcStore = vi.hoisted(() => ({ current: {} as Record<string, unknown> }))
88
const project = vi.hoisted(() => ({ nuxtVersion: undefined as string | undefined }))
99
const fetchMock = vi.hoisted(() => vi.fn())
1010
const registry = vi.hoisted(() => ({ current: { registry: 'https://registry.npmjs.org', authToken: null as string | null, authorization: null as string | null } }))
11+
const detectNpmRegistry = vi.hoisted(() => vi.fn(async () => registry.current))
1112

1213
vi.mock('std-env', async (importOriginal) => {
1314
const original = await importOriginal<typeof import('std-env')>()
@@ -37,9 +38,7 @@ vi.mock('rc9', async () => {
3738

3839
vi.mock('../../../src/utils/fetch', () => ({ fetchJson: fetchMock }))
3940

40-
vi.mock('../../../src/utils/registry', () => ({
41-
detectNpmRegistry: async () => registry.current,
42-
}))
41+
vi.mock('../../../src/utils/registry', () => ({ detectNpmRegistry }))
4342

4443
vi.mock('../../../src/utils/package-json', () => ({
4544
readDependencyPackageJson: async (name?: string) => {
@@ -165,6 +164,12 @@ describe('update check', () => {
165164
)
166165
})
167166

167+
it('ignores the project `.npmrc` when choosing where to check', async () => {
168+
fetchMock.mockResolvedValue({ latest: '4.1.0' })
169+
await checkForNuxtUpdate('/project')
170+
expect(detectNpmRegistry).toHaveBeenCalledWith(null, null)
171+
})
172+
168173
it('is silent when the network is unavailable', async () => {
169174
fetchMock.mockRejectedValue(new Error('getaddrinfo ENOTFOUND registry.npmjs.org'))
170175
await expect(checkForNuxtUpdate('/project')).resolves.toBeUndefined()

0 commit comments

Comments
 (0)