Skip to content

Commit 292b63a

Browse files
committed
fix(upgrade): recreate selected workspace lockfile
1 parent 07d86a3 commit 292b63a

3 files changed

Lines changed: 39 additions & 24 deletions

File tree

‎packages/nuxt-cli/src/commands/upgrade.ts‎

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -161,19 +161,18 @@ export default defineCommand({
161161
description: 'Force upgrade to recreate lockfile and node_modules',
162162
},
163163
channel: {
164-
type: 'string',
164+
type: 'enum',
165165
alias: 'ch',
166166
default: 'stable',
167167
description: 'Specify a channel to install from',
168-
valueHint: 'stable|nightly|v3|v4|v4-nightly|v3-nightly',
168+
options: ['stable','nightly','v3','v4','v4-nightly','v3-nightly'],
169169
},
170170
},
171171
asyncrun(ctx){
172172
constcwd=resolveRootDir(ctx.args)
173173

174174
intro(styleText('cyan','Upgrading Nuxt ...'))
175175

176-
// Check package manager
177176
const[packageManager,workspaceDir=cwd]=awaitPromise.all([detectPackageManager(cwd),findWorkspaceDir(cwd,{try: true})])
178177
if(!packageManager){
179178
logger.error(
@@ -186,19 +185,16 @@ export default defineCommand({
186185
constpackageManagerVersion=getPackageManagerVersion(packageManagerName)
187186
logger.step(`Package manager: ${styleText('cyan',packageManagerName)}${packageManagerVersion}`)
188187

189-
// Check currently installed Nuxt version
190188
constcurrentVersion=(awaitgetNuxtVersion(cwd))||'[unknown]'
191189
logger.step(`Current Nuxt version: ${styleText('cyan',currentVersion)}`)
192190

193191
constpkg=awaitreadPackageJSON(cwd).catch(()=>null)
194192

195-
// Check if Nuxt is a dependency or devDependency
196193
constnuxtDependencyType=pkg ? checkNuxtDependencyType(pkg) : 'dependencies'
197194
constcorePackages=['@nuxt/kit','@nuxt/schema','@nuxt/vite-builder','@nuxt/webpack-builder','@nuxt/rspack-builder']
198195

199196
constpackagesToUpdate=pkg ? corePackages.filter(p=>pkg.dependencies?.[p]||pkg.devDependencies?.[p]) : []
200197

201-
// Install latest version
202198
constpackageNames=['nuxt', ...packagesToUpdate]
203199
const{ npmPackages, nuxtVersion }=awaitgetRequiredNewVersion(packageNames,ctx.args.channel)
204200

@@ -217,7 +213,6 @@ export default defineCommand({
217213
}
218214
}
219215

220-
// Force install
221216
consttoRemove=['node_modules']
222217

223218
constlockFile=findLockFile(cwd,workspaceDir,lockFileCandidates)
@@ -280,13 +275,15 @@ export default defineCommand({
280275
constresolved: Array<{catalog: string,pkg: string,specifier: string}>=[]
281276
constunresolved: string[]=[]
282277

283-
for(const{ catalog, current, spec }ofcatalogUpdates){
284-
constspecifier=awaitresolveCatalogSpecifier(spec,current)
285-
if(!specifier){
278+
constspecifiers=awaitPromise.all(catalogUpdates.map(({ current, spec })=>resolveCatalogSpecifier(spec,current)))
279+
for(const[index,specifier]ofspecifiers.entries()){
280+
const{ catalog, spec }=catalogUpdates[index]!
281+
if(specifier){
282+
resolved.push({ catalog,pkg: spec.name, specifier })
283+
}
284+
else{
286285
unresolved.push(spec.name)
287-
continue
288286
}
289-
resolved.push({ catalog,pkg: spec.name, specifier })
290287
}
291288

292289
if(resolved.length>0){
@@ -347,7 +344,7 @@ export default defineCommand({
347344
recreateLockfile ? `Recreating ${forceRemovals}` : 'Deduping dependencies',
348345
recreateLockfile ? 'Lockfile recreated' : 'Dependencies deduped',
349346
{ verbose },
350-
hooks=>runDedupe({ cwd, packageManager, recreateLockfile, ...hooks}),
347+
hooks=>runDedupe({ cwd, packageManager, recreateLockfile,lockFile,...hooks}),
351348
)
352349

353350
if(failed){
@@ -373,7 +370,6 @@ export default defineCommand({
373370
logger.info(`If you encounter any issues, revert the changes and try with ${styleText('cyan','--no-force')}`)
374371
}
375372

376-
// Check installed Nuxt version again
377373
constupgradedVersion=(awaitgetNuxtVersion(cwd))||'[unknown]'
378374

379375
if(upgradedVersion==='[unknown]'){
@@ -450,7 +446,6 @@ async function withInstallSpinner(
450446
return!result.success
451447
}
452448

453-
// Find which lock file is in use since `nypm.detectPackageManager` doesn't return this
454449
exportfunctionfindLockFile(cwd: string,workspaceDir: string,lockFiles: string|Array<string>|undefined){
455450
constcandidates=typeoflockFiles==='string' ? [lockFiles] : lockFiles
456451

‎packages/nuxt-cli/src/utils/install.ts‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { ChildProcess, SpawnOptions } from 'node:child_process'
33

44
importtype{PackageManager,PackageManagerName}from'nypm'
55
import{spawn}from'node:child_process'
6-
import{statSync}from'node:fs'
6+
import{rmSync,statSync}from'node:fs'
77
import{delimiter,resolve}from'node:path'
88
importprocessfrom'node:process'
99

@@ -108,19 +108,31 @@ export async function runInstall(options: InstallOptions): Promise<InstallResult
108108
}
109109

110110
exportinterfaceDedupeOptionsextendsOmit<InstallOptions,'dependencies'|'dev'|'workspace'>{
111-
/** Delete the lockfile and resolve dependencies from scratch. */
111+
/** Delete node_modules and the lockfile, then resolve dependencies from scratch. */
112112
recreateLockfile?: boolean
113+
/** Lockfile path relative to cwd. */
114+
lockFile?: string
113115
}
114116

115117
/**
116118
* Dedupe a project's dependencies, or recreate its lockfile, with the same quiet
117119
* output handling as {@link runInstall}.
118120
*/
119121
exportasyncfunctionrunDedupe(options: DedupeOptions): Promise<InstallResult>{
122+
if(options.recreateLockfile){
123+
rmSync(resolve(options.cwd,'node_modules'),{recursive: true,force: true})
124+
constlockFiles=options.lockFile
125+
? [options.lockFile]
126+
: [options.packageManager.lockFile].flat().filter(Boolean)asstring[]
127+
for(constlockFileoflockFiles){
128+
rmSync(resolve(options.cwd,lockFile),{force: true})
129+
}
130+
returnawaitrunInstall(options)
131+
}
132+
120133
const{ exec }=awaitdedupeDependencies({
121134
cwd: options.cwd,
122135
packageManager: options.packageManager,
123-
recreateLockfile: options.recreateLockfile,
124136
dry: true,
125137
})
126138

‎packages/nuxt-cli/test/unit/utils/install.spec.ts‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import{existsSync}from'node:fs'
2-
import{chmod,mkdtemp,writeFile}from'node:fs/promises'
2+
import{chmod,mkdir,mkdtemp,writeFile}from'node:fs/promises'
33
import{tmpdir}from'node:os'
44
import{join}from'node:path'
55
importprocessfrom'node:process'
@@ -135,20 +135,28 @@ describe('runDedupe', () => {
135135
expect(lines).toEqual(['all done'])
136136
})
137137

138-
it.skipIf(process.platform==='win32')('should install after removing the lockfile when recreating it',async()=>{
138+
it.skipIf(process.platform==='win32')('should install after removing node_modules and the selected lockfile',async()=>{
139139
const{ dir, command }=awaitcreateFakePackageManager()
140-
constlockFile=join(dir,'pnpm-lock.yaml')
141-
awaitwriteFile(lockFile,'lockfileVersion: 9.0\n')
140+
constappDir=join(dir,'app')
141+
constnodeModules=join(appDir,'node_modules')
142+
constlocalLockFile=join(appDir,'pnpm-lock.yaml')
143+
constworkspaceLockFile=join(dir,'pnpm-lock.yaml')
144+
awaitmkdir(nodeModules,{recursive: true})
145+
awaitwriteFile(localLockFile,'lockfileVersion: 9.0\n')
146+
awaitwriteFile(workspaceLockFile,'lockfileVersion: 9.0\n')
142147

143148
constresult=awaitrunDedupe({
144-
cwd: dir,
149+
cwd: appDir,
145150
packageManager: {name: 'pnpm', command,lockFile: 'pnpm-lock.yaml'},
146151
recreateLockfile: true,
152+
lockFile: '../pnpm-lock.yaml',
147153
})
148154

149155
expect(result.success).toBe(true)
150156
expect(result.command).toContain(`${command} install`)
151-
expect(existsSync(lockFile)).toBe(false)
157+
expect(existsSync(nodeModules)).toBe(false)
158+
expect(existsSync(workspaceLockFile)).toBe(false)
159+
expect(existsSync(localLockFile)).toBe(true)
152160
})
153161

154162
it('should report a missing package manager instead of throwing',async()=>{

0 commit comments

Comments
 (0)