11import type { PackageJson } from 'pkg-types'
22
3+ import type { ConfigEntries } from '../../utils/config'
34import type { NuxtModule } from './_utils'
45
56import process from 'node:process'
@@ -12,7 +13,8 @@ import colors from 'picocolors'
1213import { readPackageJSON } from 'pkg-types'
1314
1415import { runCommandDef as runCommand } from '../../run-command'
15- import { updateConfig } from '../../utils/config'
16+ import { readNuxtConfig , removeNuxtConfigEntries } from '../../utils/config'
17+ import { CONFIG_KEYS } from '../../utils/config-parse'
1618import { logger } from '../../utils/logger'
1719import { logNetworkError } from '../../utils/network'
1820import { relativeToProcess } from '../../utils/paths'
@@ -98,88 +100,55 @@ async function removeModules(modules: string[], { skipInstall = false, skipConfi
98100 const dependencies = getProjectDependencies ( projectPkg )
99101
100102 if ( ! skipConfig ) {
101- let configMissing = false
102- let cancelled = false
103-
104- await updateConfig ( {
105- cwd,
106- configFile : 'nuxt.config' ,
107- onCreate ( ) {
108- configMissing = true
109- return false
110- } ,
111- async onUpdate ( config ) {
112- const arrays = ( [ [ 'modules' , config . modules ] , [ 'extends' , config . extends ] ] as const )
113- . filter ( ( [ , value ] ) => Array . isArray ( value ) ) as Array < [ string , unknown [ ] ] >
114-
115- if ( arrays . length === 0 ) {
116- return
117- }
103+ const config = await readNuxtConfig ( cwd ) . catch ( ( error ) => {
104+ logger . error ( `Failed to read ${ colors . cyan ( 'nuxt.config' ) } : ${ ( error as Error ) . message } ` )
105+ return undefined
106+ } )
118107
119- const present : string [ ] = [ ]
120- for ( const [ , items ] of arrays ) {
121- for ( const item of items ) {
122- const name = readModuleName ( item )
123- if ( name ) {
124- present . push ( name )
125- }
126- }
127- }
108+ const present = config ? CONFIG_KEYS . flatMap ( key => config [ key ] ) : [ ]
128109
129- let toRemove : Set < string >
130- if ( modules . length === 0 ) {
131- if ( present . length === 0 ) {
132- return
133- }
110+ let toRemove = new Set ( modules )
111+ if ( config && modules . length === 0 && present . length > 0 ) {
112+ const picked = await multiselect ( {
113+ message : 'Select modules to remove:' ,
114+ options : present . map ( m => ( { value : m , label : m } ) ) ,
115+ required : true ,
116+ } )
134117
135- const picked = await multiselect ( {
136- message : 'Select modules to remove:' ,
137- options : present . map ( m => ( { value : m , label : m } ) ) ,
138- required : true ,
139- } )
118+ if ( isCancel ( picked ) ) {
119+ cancel ( 'No modules selected.' )
120+ return false
121+ }
140122
141- if ( isCancel ( picked ) ) {
142- cancelled = true
143- return
144- }
123+ toRemove = new Set ( picked as string [ ] )
124+ }
145125
146- toRemove = new Set ( picked as string [ ] )
147- }
148- else {
149- toRemove = new Set ( modules )
126+ if ( config ) {
127+ const doomed : ConfigEntries = { }
128+ for ( const key of CONFIG_KEYS ) {
129+ // A package may be configured through a subpath (`maz-ui/nuxt`) while the
130+ // user asks to remove the package itself.
131+ const names = config [ key ] . filter ( name => toRemove . has ( name ) || toRemove . has ( basePackageName ( name ) ) )
132+ if ( ! names . length ) {
133+ continue
150134 }
151-
152- for ( const [ key , items ] of arrays ) {
153- for ( let i = items . length - 1 ; i >= 0 ; i -- ) {
154- const name = readModuleName ( items [ i ] )
155- // A package may be configured through a subpath (`maz-ui/nuxt`) while the
156- // user asks to remove the package itself.
157- if ( ! name || ! ( toRemove . has ( name ) || toRemove . has ( basePackageName ( name ) ) ) ) {
158- continue
159- }
160- logger . info ( `Removing ${ colors . cyan ( name ) } from the ${ colors . cyan ( key ) } ` )
161- items . splice ( i , 1 )
162- removedFromConfig . push ( name )
163- }
135+ for ( const name of names ) {
136+ logger . info ( `Removing ${ colors . cyan ( name ) } from the ${ colors . cyan ( key ) } ` )
164137 }
165- } ,
166- } ) . catch ( ( error ) => {
167- if ( configMissing ) {
168- return
138+ doomed [ key ] = names
139+ removedFromConfig . push ( ...names )
169140 }
170- logger . error ( `Failed to update ${ colors . cyan ( 'nuxt.config' ) } : ${ error . message } ` )
171- logger . error ( `Please manually remove ${ colors . cyan ( modules . join ( ', ' ) || 'the relevant modules' ) } from ${ colors . cyan ( 'nuxt.config.ts' ) } ` )
172- } )
173141
174- if ( cancelled ) {
175- cancel ( 'No modules selected.' )
176- return false
142+ await removeNuxtConfigEntries ( config , doomed ) . catch ( ( error ) => {
143+ logger . error ( `Failed to update ${ colors . cyan ( 'nuxt.config' ) } : ${ ( error as Error ) . message } ` )
144+ logger . error ( `Please manually remove ${ colors . cyan ( modules . join ( ', ' ) || 'the relevant modules' ) } from ${ colors . cyan ( 'nuxt.config.ts' ) } ` )
145+ } )
177146 }
178147
179148 if ( modules . length === 0 && removedFromConfig . length === 0 ) {
180- cancel ( configMissing
181- ? `No ${ colors . cyan ( 'nuxt.config' ) } found in ${ colors . cyan ( relativeToProcess ( cwd ) ) } .`
182- : `No modules configured in ${ colors . cyan ( 'nuxt.config' ) } .` )
149+ cancel ( config
150+ ? `No modules configured in ${ colors . cyan ( 'nuxt.config' ) } .`
151+ : `No ${ colors . cyan ( 'nuxt.config' ) } found in ${ colors . cyan ( relativeToProcess ( cwd ) ) } .` )
183152 return false
184153 }
185154 }
@@ -263,16 +232,6 @@ async function removeModules(modules: string[], { skipInstall = false, skipConfi
263232 return true
264233}
265234
266- function readModuleName ( item : unknown ) : string | null {
267- if ( typeof item === 'string' ) {
268- return item
269- }
270- if ( Array . isArray ( item ) && typeof item [ 0 ] === 'string' ) {
271- return item [ 0 ]
272- }
273- return null
274- }
275-
276235function resolveModuleName ( input : string , modulesDB : NuxtModule [ ] , installed : Set < string > ) : string {
277236 if ( installed . has ( input ) ) {
278237 return input
0 commit comments