Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add user-specified registry support (from npmrc) #470

Merged
merged 8 commits into from
Sep 19, 2024
45 changes: 42 additions & 3 deletions src/commands/module/add.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import * as fs from 'node:fs'
import { homedir } from 'node:os'
import { join } from 'node:path'
import type { FileHandle } from 'node:fs/promises'
import { defineCommand } from 'citty'
import { resolve } from 'pathe'
import consola from 'consola'
Expand Down Expand Up @@ -216,9 +220,8 @@ async function resolveModule(

// Fetch package on npm
pkgVersion = pkgVersion || 'latest'
const pkg = await $fetch(
`https://registry.npmjs.org/${pkgName}/${pkgVersion}`,
)
const registry = await detectNpmRegistry()
const pkg = await $fetch(`${registry}/${pkgName}/${pkgVersion}`)
const pkgDependencies = Object.assign(
pkg.dependencies || {},
pkg.devDependencies || {},
Expand Down Expand Up @@ -248,3 +251,39 @@ async function resolveModule(
pkgVersion,
}
}

async function detectNpmRegistry() {
if (process.env.COREPACK_NPM_REGISTRY) {
return process.env.COREPACK_NPM_REGISTRY
}
const userNpmrcPath = join(homedir(), '.npmrc')
const cwdNpmrcPath = join(process.cwd(), '.npmrc')
const registry = await getRegistryFromFile([cwdNpmrcPath, userNpmrcPath])
if (registry) {
process.env.COREPACK_NPM_REGISTRY = registry
}
return registry || 'https://registry.npmjs.org'
}

async function getRegistryFromFile(paths: string[]) {
for (const npmrcPath of paths) {
let fd: FileHandle | undefined
try {
fd = await fs.promises.open(npmrcPath, 'r')
if (await fd.stat().then(r => r.isFile())) {
const npmrcContent = await fd.readFile('utf-8')
const registryMatch = npmrcContent.match(/registry=(.*)/)
if (registryMatch) {
return registryMatch[1].trim()
}
}
}
catch {
// swallow errors as file does not exist
}
finally {
await fd?.close()
}
}
return null
}