diff --git a/knip.json b/knip.json index af7e03919..6d45d0a9d 100644 --- a/knip.json +++ b/knip.json @@ -20,6 +20,7 @@ "c12", "chokidar", "clipboardy", + "confbox", "consola", "defu", "exsolve", diff --git a/packages/nuxi/package.json b/packages/nuxi/package.json index 96bd1703a..4dc5db84f 100644 --- a/packages/nuxi/package.json +++ b/packages/nuxi/package.json @@ -48,6 +48,7 @@ "chokidar": "^4.0.3", "citty": "^0.1.6", "clipboardy": "^4.0.0", + "confbox": "^0.2.2", "consola": "^3.4.2", "defu": "^6.1.4", "exsolve": "^1.0.5", diff --git a/packages/nuxi/src/commands/module/_utils.ts b/packages/nuxi/src/commands/module/_utils.ts index e10993bff..d61cfed04 100644 --- a/packages/nuxi/src/commands/module/_utils.ts +++ b/packages/nuxi/src/commands/module/_utils.ts @@ -1,3 +1,4 @@ +import { parseINI } from 'confbox' import { $fetch } from 'ofetch' import { readPackageJSON } from 'pkg-types' import { coerce, satisfies } from 'semver' @@ -124,3 +125,25 @@ export async function getNuxtVersion(cwd: string) { const pkgDep = pkg?.dependencies?.nuxt || pkg?.devDependencies?.nuxt return (pkgDep && coerce(pkgDep)?.version) || '3.0.0' } + +export function getRegistryFromContent(content: string, scope: string | null) { + try { + const npmConfig = parseINI>(content) + + if (scope) { + const scopeKey = `${scope}:registry` + if (npmConfig[scopeKey]) { + return npmConfig[scopeKey].trim() + } + } + + if (npmConfig.registry) { + return npmConfig.registry.trim() + } + + return null + } + catch { + return null + } +} diff --git a/packages/nuxi/src/commands/module/add.ts b/packages/nuxi/src/commands/module/add.ts index 16a52953c..062faca24 100644 --- a/packages/nuxi/src/commands/module/add.ts +++ b/packages/nuxi/src/commands/module/add.ts @@ -20,7 +20,7 @@ import { joinURL } from 'ufo' import { runCommand } from '../../run' import { logger } from '../../utils/logger' import { cwdArgs, logLevelArgs } from '../_shared' -import { checkNuxtCompatibility, fetchModules, getNuxtVersion } from './_utils' +import { checkNuxtCompatibility, fetchModules, getNuxtVersion, getRegistryFromContent } from './_utils' interface RegistryMeta { registry: string @@ -406,20 +406,10 @@ async function getRegistryFromFile(paths: string[], scope: string | null) { fd = await fs.promises.open(npmrcPath, 'r') if (await fd.stat().then(r => r.isFile())) { const npmrcContent = await fd.readFile('utf-8') + const registry = getRegistryFromContent(npmrcContent, scope) - if (scope) { - const scopedRegex = new RegExp(`^${scope}:registry=(.+)$`, 'm') - const scopedMatch = npmrcContent.match(scopedRegex)?.[1] - if (scopedMatch) { - return scopedMatch.trim() - } - } - - // If no scoped registry found or no scope provided, look for the default registry - const defaultRegex = /^\s*registry=(.+)$/m - const defaultMatch = npmrcContent.match(defaultRegex)?.[1] - if (defaultMatch) { - return defaultMatch.trim() + if (registry) { + return registry } } } diff --git a/packages/nuxi/test/unit/commands/module/_utils.test.ts b/packages/nuxi/test/unit/commands/module/_utils.test.ts new file mode 100644 index 000000000..3bdc040e4 --- /dev/null +++ b/packages/nuxi/test/unit/commands/module/_utils.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it } from 'vitest' +import { getRegistryFromContent } from '../../../../src/commands/module/_utils' + +describe('getRegistryFromContent', () => { + it('extracts scoped registry when scope is provided', () => { + const content = ` +registry=https://registry.npmjs.org/ +@myorg:registry=https://my-registry.org/ +@another:registry=https://another-registry.org/ + ` + + expect(getRegistryFromContent(content, '@myorg')).toBe('https://my-registry.org/') + expect(getRegistryFromContent(content, '@another')).toBe('https://another-registry.org/') + }) + + it('extracts default registry when scope is not provided', () => { + const content = ` +registry=https://registry.npmjs.org/ +@myorg:registry=https://my-registry.org/ + ` + + expect(getRegistryFromContent(content, null)).toBe('https://registry.npmjs.org/') + }) + + it('extracts default registry when scope is provided but not found', () => { + const content = ` +registry=https://registry.npmjs.org/ +@myorg:registry=https://my-registry.org/ + ` + + expect(getRegistryFromContent(content, '@notfound')).toBe('https://registry.npmjs.org/') + }) + + it('returns null when no registry is found', () => { + const content = ` +# some npmrc content without registry +some-other-setting=value + ` + + expect(getRegistryFromContent(content, null)).toBeNull() + expect(getRegistryFromContent(content, '@myorg')).toBeNull() + }) + + it('handles empty content', () => { + expect(getRegistryFromContent('', null)).toBeNull() + expect(getRegistryFromContent('', '@myorg')).toBeNull() + }) + + it('extracts registry from line with comments', () => { + const content = ` +registry=https://registry.npmjs.org/ # with comment +@myorg:registry=https://my-registry.org/ # another comment + ` + + expect(getRegistryFromContent(content, null)).toBe('https://registry.npmjs.org/') + expect(getRegistryFromContent(content, '@myorg')).toBe('https://my-registry.org/') + }) +}) diff --git a/packages/nuxt-cli/package.json b/packages/nuxt-cli/package.json index 87cdee5a0..06e35983a 100644 --- a/packages/nuxt-cli/package.json +++ b/packages/nuxt-cli/package.json @@ -37,6 +37,7 @@ "chokidar": "^4.0.3", "citty": "^0.1.6", "clipboardy": "^4.0.0", + "confbox": "^0.2.2", "consola": "^3.4.2", "defu": "^6.1.4", "exsolve": "^1.0.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e9bd3ab3..187f4e52a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -127,6 +127,9 @@ importers: clipboardy: specifier: ^4.0.0 version: 4.0.0 + confbox: + specifier: ^0.2.2 + version: 0.2.2 consola: specifier: ^3.4.2 version: 3.4.2 @@ -229,6 +232,9 @@ importers: clipboardy: specifier: ^4.0.0 version: 4.0.0 + confbox: + specifier: ^0.2.2 + version: 0.2.2 consola: specifier: ^3.4.2 version: 3.4.2