Skip to content

Commit 571cc3a

Browse files
committed
refactor: extract npm registry resolution into a shared util
1 parent a04ec72 commit 571cc3a

4 files changed

Lines changed: 126 additions & 120 deletions

File tree

‎packages/nuxt-cli/src/commands/module/_utils.ts‎

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { PackageJson } from 'pkg-types'
44
import{existsSync}from'node:fs'
55

66
import{confirm,isCancel}from'@clack/prompts'
7-
import{parseINI}from'confbox'
87
import{$fetch}from'ofetch'
98
import{resolve}from'pathe'
109
importcolorsfrom'picocolors'
@@ -127,28 +126,6 @@ export function checkNuxtCompatibility(
127126
})
128127
}
129128

130-
exportfunctiongetRegistryFromContent(content: string,scope: string|null){
131-
try{
132-
constnpmConfig=parseINI<Record<string,string|undefined>>(content)
133-
134-
if(scope){
135-
constscopeKey=`${scope}:registry`
136-
if(npmConfig[scopeKey]){
137-
returnnpmConfig[scopeKey].trim()
138-
}
139-
}
140-
141-
if(npmConfig.registry){
142-
returnnpmConfig.registry.trim()
143-
}
144-
145-
returnnull
146-
}
147-
catch{
148-
returnnull
149-
}
150-
}
151-
152129
exportfunctiongetProjectDependencies(projectPkg: PackageJson): Set<string>{
153130
returnnewSet([
154131
...Object.keys(projectPkg.dependencies||{}),

‎packages/nuxt-cli/src/commands/module/add.ts‎

Lines changed: 3 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
importtype{FileHandle}from'node:fs/promises'
21
importtype{PackageManager}from'nypm'
32
importtype{PackageJson}from'pkg-types'
43

4+
importtype{RegistryMeta}from'../../utils/registry'
55
importtype{NuxtModule}from'./_utils'
6-
import*asfsfrom'node:fs'
7-
import{homedir}from'node:os'
8-
import{join}from'node:path'
96
importprocessfrom'node:process'
107

118
import{cancel,confirm,isCancel,select,spinner}from'@clack/prompts'
@@ -23,22 +20,15 @@ import { runCommandDef as runCommand } from '../../run'
2320
import{createInstallLog,resolvePackageManagerDescriptor,runInstall,takeUnreportedIgnoredBuilds}from'../../utils/install'
2421
import{logger}from'../../utils/logger'
2522
import{logNetworkError}from'../../utils/network'
23+
import{detectNpmRegistry}from'../../utils/registry'
2624
import{getNuxtVersion}from'../../utils/versions'
2725
import{cwdArgs,logLevelArgs}from'../_shared'
2826
importprepareCommandfrom'../prepare'
2927
import{selectModulesAutocomplete}from'./_autocomplete'
30-
import{checkNuxtCompatibility,ensureNuxtDependency,fetchModules,forwardCommandArgs,getProjectDependencies,getRegistryFromContent,isPnpmWorkspace,MODULES_API_URL}from'./_utils'
28+
import{checkNuxtCompatibility,ensureNuxtDependency,fetchModules,forwardCommandArgs,getProjectDependencies,isPnpmWorkspace,MODULES_API_URL}from'./_utils'
3129

32-
constPROTOCOL_RE=/^https?:\/\//
33-
constTRAILING_SLASH_RE=/\/$/
34-
constREGEX_SPECIAL_RE=/[.*+?^${}()|[\]\\]/g
3530
constWHITESPACE_RE=/\s/
3631

37-
interfaceRegistryMeta{
38-
registry: string
39-
authToken: string|null
40-
}
41-
4232
interfaceResolvedModule{
4333
nuxtModule?: NuxtModule
4434
pkg: string
@@ -472,86 +462,3 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
472462
.map(([name])=>name),
473463
}
474464
}
475-
476-
functiongetNpmrcPaths(): string[]{
477-
constuserNpmrcPath=join(homedir(),'.npmrc')
478-
constcwdNpmrcPath=join(process.cwd(),'.npmrc')
479-
480-
return[cwdNpmrcPath,userNpmrcPath]
481-
}
482-
483-
asyncfunctiongetAuthToken(registry: RegistryMeta['registry']): Promise<RegistryMeta['authToken']>{
484-
constpaths=getNpmrcPaths()
485-
constregistryHost=registry.replace(PROTOCOL_RE,'').replace(TRAILING_SLASH_RE,'').replace(REGEX_SPECIAL_RE,'\\$&')
486-
constauthTokenRegex=newRegExp(`^//${registryHost}/:_authToken=(.+)$`,'m')
487-
488-
for(constnpmrcPathofpaths){
489-
letfd: FileHandle|undefined
490-
try{
491-
fd=awaitfs.promises.open(npmrcPath,'r')
492-
if(awaitfd.stat().then(r=>r.isFile())){
493-
constnpmrcContent=awaitfd.readFile('utf-8')
494-
constauthTokenMatch=npmrcContent.match(authTokenRegex)?.[1]
495-
496-
if(authTokenMatch){
497-
returnauthTokenMatch.trim()
498-
}
499-
}
500-
}
501-
catch{
502-
// swallow errors as file does not exist
503-
}
504-
finally{
505-
awaitfd?.close()
506-
}
507-
}
508-
509-
returnnull
510-
}
511-
512-
asyncfunctiondetectNpmRegistry(scope: string|null): Promise<RegistryMeta>{
513-
constregistry=awaitgetRegistry(scope)
514-
constauthToken=awaitgetAuthToken(registry)
515-
516-
return{
517-
registry,
518-
authToken,
519-
}
520-
}
521-
522-
asyncfunctiongetRegistry(scope: string|null): Promise<string>{
523-
if(process.env.COREPACK_NPM_REGISTRY){
524-
returnprocess.env.COREPACK_NPM_REGISTRY
525-
}
526-
constregistry=awaitgetRegistryFromFile(getNpmrcPaths(),scope)
527-
528-
if(registry){
529-
process.env.COREPACK_NPM_REGISTRY=registry
530-
}
531-
532-
returnregistry||'https://registry.npmjs.org'
533-
}
534-
535-
asyncfunctiongetRegistryFromFile(paths: string[],scope: string|null){
536-
for(constnpmrcPathofpaths){
537-
letfd: FileHandle|undefined
538-
try{
539-
fd=awaitfs.promises.open(npmrcPath,'r')
540-
if(awaitfd.stat().then(r=>r.isFile())){
541-
constnpmrcContent=awaitfd.readFile('utf-8')
542-
constregistry=getRegistryFromContent(npmrcContent,scope)
543-
544-
if(registry){
545-
returnregistry
546-
}
547-
}
548-
}
549-
catch{
550-
// swallow errors as file does not exist
551-
}
552-
finally{
553-
awaitfd?.close()
554-
}
555-
}
556-
returnnull
557-
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
importtype{FileHandle}from'node:fs/promises'
2+
3+
import*asfsfrom'node:fs'
4+
import{homedir}from'node:os'
5+
import{join}from'node:path'
6+
importprocessfrom'node:process'
7+
8+
import{parseINI}from'confbox'
9+
10+
constPROTOCOL_RE=/^https?:\/\//
11+
constTRAILING_SLASH_RE=/\/$/
12+
constREGEX_SPECIAL_RE=/[.*+?^${}()|[\]\\]/g
13+
14+
exportinterfaceRegistryMeta{
15+
registry: string
16+
authToken: string|null
17+
}
18+
19+
exportfunctiongetRegistryFromContent(content: string,scope: string|null): string|null{
20+
try{
21+
constnpmConfig=parseINI<Record<string,string|undefined>>(content)
22+
23+
if(scope){
24+
constscopeKey=`${scope}:registry`
25+
if(npmConfig[scopeKey]){
26+
returnnpmConfig[scopeKey].trim()
27+
}
28+
}
29+
30+
if(npmConfig.registry){
31+
returnnpmConfig.registry.trim()
32+
}
33+
34+
returnnull
35+
}
36+
catch{
37+
returnnull
38+
}
39+
}
40+
41+
functiongetNpmrcPaths(): string[]{
42+
constuserNpmrcPath=join(homedir(),'.npmrc')
43+
constcwdNpmrcPath=join(process.cwd(),'.npmrc')
44+
45+
return[cwdNpmrcPath,userNpmrcPath]
46+
}
47+
48+
asyncfunctiongetRegistryFromFile(paths: string[],scope: string|null){
49+
for(constnpmrcPathofpaths){
50+
letfd: FileHandle|undefined
51+
try{
52+
fd=awaitfs.promises.open(npmrcPath,'r')
53+
if(awaitfd.stat().then(r=>r.isFile())){
54+
constnpmrcContent=awaitfd.readFile('utf-8')
55+
constregistry=getRegistryFromContent(npmrcContent,scope)
56+
57+
if(registry){
58+
returnregistry
59+
}
60+
}
61+
}
62+
catch{
63+
// swallow errors as file does not exist
64+
}
65+
finally{
66+
awaitfd?.close()
67+
}
68+
}
69+
returnnull
70+
}
71+
72+
asyncfunctiongetRegistry(scope: string|null): Promise<string>{
73+
if(process.env.COREPACK_NPM_REGISTRY){
74+
returnprocess.env.COREPACK_NPM_REGISTRY
75+
}
76+
constregistry=awaitgetRegistryFromFile(getNpmrcPaths(),scope)
77+
78+
if(registry){
79+
process.env.COREPACK_NPM_REGISTRY=registry
80+
}
81+
82+
returnregistry||'https://registry.npmjs.org'
83+
}
84+
85+
asyncfunctiongetAuthToken(registry: RegistryMeta['registry']): Promise<RegistryMeta['authToken']>{
86+
constpaths=getNpmrcPaths()
87+
constregistryHost=registry.replace(PROTOCOL_RE,'').replace(TRAILING_SLASH_RE,'').replace(REGEX_SPECIAL_RE,'\\$&')
88+
constauthTokenRegex=newRegExp(`^//${registryHost}/:_authToken=(.+)$`,'m')
89+
90+
for(constnpmrcPathofpaths){
91+
letfd: FileHandle|undefined
92+
try{
93+
fd=awaitfs.promises.open(npmrcPath,'r')
94+
if(awaitfd.stat().then(r=>r.isFile())){
95+
constnpmrcContent=awaitfd.readFile('utf-8')
96+
constauthTokenMatch=npmrcContent.match(authTokenRegex)?.[1]
97+
98+
if(authTokenMatch){
99+
returnauthTokenMatch.trim()
100+
}
101+
}
102+
}
103+
catch{
104+
// swallow errors as file does not exist
105+
}
106+
finally{
107+
awaitfd?.close()
108+
}
109+
}
110+
111+
returnnull
112+
}
113+
114+
exportasyncfunctiondetectNpmRegistry(scope: string|null): Promise<RegistryMeta>{
115+
constregistry=awaitgetRegistry(scope)
116+
constauthToken=awaitgetAuthToken(registry)
117+
118+
return{
119+
registry,
120+
authToken,
121+
}
122+
}

packages/nuxt-cli/test/unit/commands/module/_utils.spec.ts renamed to packages/nuxt-cli/test/unit/utils/registry.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import{describe,expect,it}from'vitest'
2-
import{getRegistryFromContent}from'../../../../src/commands/module/_utils'
2+
import{getRegistryFromContent}from'../../../src/utils/registry'
33

44
describe('getRegistryFromContent',()=>{
55
it('extracts scoped registry when scope is provided',()=>{

0 commit comments

Comments
 (0)