@@ -13,7 +13,7 @@ import { detectPackageManager, packageManagers } from 'nypm'
1313import { resolve } from 'pathe'
1414import { readPackageJSON } from 'pkg-types'
1515import { joinURL } from 'ufo'
16- import { satisfies } from 'verkit'
16+ import { findMaxSatisfying , satisfies } from 'verkit'
1717
1818import { runCommandDef as runCommand } from '../../run-command'
1919import { addNuxtConfigEntries , createNuxtConfig , readNuxtConfig } from '../../utils/config'
@@ -88,7 +88,7 @@ export function defineAddCommand({ layers = false }: { layers?: boolean } = {})
8888 process . exit ( 1 )
8989 }
9090
91- // If no modules specified, show interactive search
91+ let modulesDB : NuxtModule [ ]
9292 if ( modules . length === 0 ) {
9393 const modulesSpinner = spinner ( )
9494 modulesSpinner . start ( 'Fetching available modules' )
@@ -102,28 +102,36 @@ export function defineAddCommand({ layers = false }: { layers?: boolean } = {})
102102 getNuxtVersion ( cwd ) ,
103103 ] )
104104
105- const compatibleModules = allModules . filter ( m =>
105+ modulesDB = allModules
106+ const compatibleModules = modulesDB . filter ( m =>
106107 ! m . compatibility . nuxt || checkNuxtCompatibility ( m , nuxtVersion ) ,
107108 )
108109
109110 modulesSpinner . stop ( 'Modules loaded' )
110111
111- const result = await selectModulesAutocomplete ( {
112+ const selection = await selectModulesAutocomplete ( {
112113 modules : compatibleModules ,
113114 message : 'Search modules to add (Esc to finish):' ,
114115 } )
116+ modules = selection . selected
115117
116- if ( result . selected . length === 0 ) {
118+ if ( modules . length === 0 ) {
117119 cancel ( 'No modules selected.' )
118120 process . exit ( 0 )
119121 }
120-
121- modules = result . selected
122+ }
123+ else {
124+ modulesDB = await fetchModules ( ) . catch ( ( err ) => {
125+ logNetworkError ( err , { url : MODULES_API_URL , level : 'warn' , prefix : 'Cannot search in the Nuxt Modules database.' } )
126+ return [ ]
127+ } )
122128 }
123129
130+ let nuxtVersionPromise : Promise < string > | undefined
131+ const getProjectNuxtVersion = ( ) => nuxtVersionPromise ||= getNuxtVersion ( cwd )
124132 const resolvedModules : ResolvedModule [ ] = [ ]
125- for ( const moduleName of modules ) {
126- const resolvedModule = await resolveModule ( moduleName , cwd )
133+ for ( const moduleName of new Set ( modules ) ) {
134+ const resolvedModule = await resolveModule ( moduleName , cwd , modulesDB , getProjectNuxtVersion )
127135 if ( resolvedModule ) {
128136 resolvedModules . push ( resolvedModule )
129137 }
@@ -142,7 +150,6 @@ export function defineAddCommand({ layers = false }: { layers?: boolean } = {})
142150 process . exit ( 1 )
143151 }
144152
145- // Run prepare command if install is not skipped
146153 if ( ! ctx . args . skipInstall ) {
147154 await runCommand ( prepareCommand , forwardCommandArgs ( ctx . args ) )
148155 }
@@ -154,7 +161,6 @@ export default defineAddCommand()
154161
155162// -- Internal Utils --
156163async function addModules ( modules : ResolvedModule [ ] , { skipInstall = false , skipConfig = false , cwd, dev = false , packageManager : packageManagerName , logLevel } : { skipInstall ?: boolean , skipConfig ?: boolean , cwd : string , dev ?: boolean , packageManager ?: string , logLevel ?: string } , projectPkg : PackageJson ) : Promise < boolean > {
157- // Add dependencies
158164 if ( ! skipInstall ) {
159165 const installedModules : ResolvedModule [ ] = [ ]
160166 const notInstalledModules : ResolvedModule [ ] = [ ]
@@ -230,7 +236,6 @@ async function addModules(modules: ResolvedModule[], { skipInstall = false, skip
230236 }
231237 }
232238
233- // Update nuxt.config.ts
234239 if ( ! skipConfig ) {
235240 try {
236241 let config = await readNuxtConfig ( cwd )
@@ -258,6 +263,7 @@ async function addModules(modules: ResolvedModule[], { skipInstall = false, skip
258263 catch ( error ) {
259264 logger . error ( `Failed to update ${ styleText ( 'cyan' , 'nuxt.config' ) } : ${ ( error as Error ) . message } ` )
260265 logger . error ( `Please manually add ${ styleText ( 'cyan' , modules . map ( module => module . specifier ) . join ( ', ' ) ) } to ${ styleText ( 'cyan' , 'nuxt.config.ts' ) } ` )
266+ return false
261267 }
262268 }
263269
@@ -342,7 +348,7 @@ export default defineNuxtConfig({
342348})`
343349}
344350
345- async function resolveModule ( moduleName : string , cwd : string ) : Promise < ModuleResolution > {
351+ async function resolveModule ( moduleName : string , cwd : string , modulesDB : NuxtModule [ ] , getProjectNuxtVersion : ( ) => Promise < string > ) : Promise < ModuleResolution > {
346352 const spec = parseModuleSpec ( moduleName )
347353
348354 if ( ! spec ) {
@@ -353,11 +359,6 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
353359 let { pkgName, pkgVersion } = spec
354360 let subpath = spec . subpath
355361
356- const modulesDB = await fetchModules ( ) . catch ( ( err ) => {
357- logNetworkError ( err , { url : MODULES_API_URL , level : 'warn' , prefix : 'Cannot search in the Nuxt Modules database.' } )
358- return [ ]
359- } )
360-
361362 const bareName = subpath ? `${ pkgName } /${ subpath } ` : pkgName
362363 const matchedModule = modulesDB . find (
363364 module =>
@@ -377,8 +378,7 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
377378 }
378379
379380 if ( matchedModule && matchedModule . compatibility . nuxt ) {
380- // Get local Nuxt version
381- const nuxtVersion = await getNuxtVersion ( cwd )
381+ const nuxtVersion = await getProjectNuxtVersion ( )
382382
383383 // Check for Module Compatibility
384384 if ( ! checkNuxtCompatibility ( matchedModule , nuxtVersion ) ) {
@@ -449,7 +449,7 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
449449 version = pkgDetails [ 'dist-tags' ] [ version ]
450450 }
451451 else {
452- version = Object . keys ( pkgDetails . versions ) ?. findLast ( v => satisfies ( v , version ) ) || version
452+ version = findMaxSatisfying ( Object . keys ( pkgDetails . versions || { } ) , version ) || version
453453 }
454454
455455 const pkg = pkgDetails . versions [ version ! ] || { }
0 commit comments