diff --git a/packages/nuxi/src/commands/init.ts b/packages/nuxi/src/commands/init.ts index fd212be4..4d1cbf74 100644 --- a/packages/nuxi/src/commands/init.ts +++ b/packages/nuxi/src/commands/init.ts @@ -33,6 +33,43 @@ const pms: Record = { // this is for type safety to prompt updating code in nuxi when nypm adds a new package manager const packageManagerOptions = Object.keys(pms) as PackageManagerName[] +async function getModuleDependencies(moduleName: string) { + try { + const response = await $fetch(`https://registry.npmjs.org/${moduleName}/latest`) + const dependencies = response.dependencies || {} + return Object.keys(dependencies) + } + catch (err) { + logger.warn(`Could not get dependencies for ${moduleName}: ${err}`) + return [] + } +} + +function filterModules(modules: string[], allDependencies: Record) { + const result = { + toInstall: [] as string[], + skipped: [] as string[], + } + + for (const module of modules) { + const isDependency = modules.some((otherModule) => { + if (otherModule === module) + return false + const deps = allDependencies[otherModule] || [] + return deps.includes(module) + }) + + if (isDependency) { + result.skipped.push(module) + } + else { + result.toInstall.push(module) + } + } + + return result +} + export default defineCommand({ meta: { name: 'init', @@ -297,7 +334,20 @@ export default defineCommand({ } if (selectedOfficialModules.length > 0) { - modulesToAdd.push(...(selectedOfficialModules as unknown as string[])) + const modules = selectedOfficialModules as unknown as string[] + + const allDependencies = Object.fromEntries( + await Promise.all(modules.map(async module => + [module, await getModuleDependencies(module)] as const, + )), + ) + + const { toInstall, skipped } = filterModules(modules, allDependencies) + + if (skipped.length) { + logger.info(`The following modules are already included as dependencies of another module and will not be installed: ${skipped.map(m => colors.cyan(m)).join(', ')}`) + } + modulesToAdd.push(...toInstall) } } }